mirror of https://github.com/Mabbs/mabbs.github.io
Update 6 files
- /_tools/blogquine.py - /_tools/serv00_post-receive - /_tools/envs_post-receive - /_data/other_repo_list.csv - /deploy.sh - /.readthedocs.yamlmaster
parent
2036ee2c4f
commit
932e310f9d
|
|
@ -12,5 +12,5 @@ build:
|
||||||
- mkdir Mabbs
|
- mkdir Mabbs
|
||||||
- curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
- curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
||||||
- bundle exec jekyll build --destination $READTHEDOCS_OUTPUT/html
|
- bundle exec jekyll build --destination $READTHEDOCS_OUTPUT/html
|
||||||
- python3 _tools/blogquine.py $READTHEDOCS_OUTPUT/html MayxBlog.7z
|
- python3 _tools/blogquine.py --src-dir blog --quine-dir blog $READTHEDOCS_OUTPUT/html MayxBlog.7z
|
||||||
- mv MayxBlog.7z $READTHEDOCS_OUTPUT/html
|
- mv MayxBlog.7z $READTHEDOCS_OUTPUT/html
|
||||||
|
|
@ -44,7 +44,6 @@ https://gitea.sciotech.cn/mayx/blog
|
||||||
https://gitea.micro-stack.org/mayx/blog
|
https://gitea.micro-stack.org/mayx/blog
|
||||||
http://106.54.211.95:3000/mayx/blog
|
http://106.54.211.95:3000/mayx/blog
|
||||||
http://172.172.102.93:3000/mayx/blog
|
http://172.172.102.93:3000/mayx/blog
|
||||||
http://120.24.249.56/mayx/blog
|
|
||||||
http://120.211.66.170:8418/mayx/blog
|
http://120.211.66.170:8418/mayx/blog
|
||||||
http://209.127.59.74:3000/mayx/blog
|
http://209.127.59.74:3000/mayx/blog
|
||||||
http://121.41.2.71:3000/mayx/blog
|
http://121.41.2.71:3000/mayx/blog
|
||||||
|
|
@ -109,7 +108,6 @@ http://36.138.125.206:3000/mayx/blog_cn
|
||||||
https://git.crystalyx.net/mayx/blog
|
https://git.crystalyx.net/mayx/blog
|
||||||
https://gitea.grxe.io/mayx/blog
|
https://gitea.grxe.io/mayx/blog
|
||||||
https://gitea.accept.dev.dbf.nl/mayx/blog
|
https://gitea.accept.dev.dbf.nl/mayx/blog
|
||||||
https://git.jhossain.online/mayx/blog
|
|
||||||
https://barhoum-lab.fr/mayx/blog
|
https://barhoum-lab.fr/mayx/blog
|
||||||
http://gitea.snailtrack.cn/mayx/blog_cn
|
http://gitea.snailtrack.cn/mayx/blog_cn
|
||||||
https://code.draussenfunker.de/mayx/blog_cn
|
https://code.draussenfunker.de/mayx/blog_cn
|
||||||
|
|
@ -120,7 +118,6 @@ https://gitea.malxte.de/mayx/blog
|
||||||
https://git.nozora.top/mayx/blog
|
https://git.nozora.top/mayx/blog
|
||||||
https://git.edenit.co.kr/mayx/blog
|
https://git.edenit.co.kr/mayx/blog
|
||||||
https://git.catgirlsneed.homes/mayx/blog
|
https://git.catgirlsneed.homes/mayx/blog
|
||||||
http://47.108.255.216:3000/mayx/blog_cn
|
|
||||||
http://210.75.240.13:3000/mayx/blog_cn
|
http://210.75.240.13:3000/mayx/blog_cn
|
||||||
http://git.hbg99.com:8080/mayx/blog_cn
|
http://git.hbg99.com:8080/mayx/blog_cn
|
||||||
https://git.eplg.services/mayx/blog
|
https://git.eplg.services/mayx/blog
|
||||||
|
|
@ -135,8 +132,6 @@ http://124.71.169.183:3000/mayx/blog
|
||||||
https://git.msoucy.me/mayx/blog
|
https://git.msoucy.me/mayx/blog
|
||||||
http://140.120.108.238:49308/mayx/blog
|
http://140.120.108.238:49308/mayx/blog
|
||||||
http://git.chilidoginteractive.com:3000/mayx/blog_cn
|
http://git.chilidoginteractive.com:3000/mayx/blog_cn
|
||||||
http://git.uhfdemo.com/mayx/blog_cn
|
|
||||||
http://43.143.142.38:7001/mayx/blog_cn
|
|
||||||
https://git.panda-number.one/mayx/blog
|
https://git.panda-number.one/mayx/blog
|
||||||
https://datacortex.pl/mayx/blog
|
https://datacortex.pl/mayx/blog
|
||||||
https://gitea.keymantek.com:777/mayx/blog
|
https://gitea.keymantek.com:777/mayx/blog
|
||||||
|
|
@ -173,7 +168,6 @@ https://gitbucket.aint-no.info/mayx/blog
|
||||||
https://git.wikeo.ovh/mayx/blog
|
https://git.wikeo.ovh/mayx/blog
|
||||||
https://devcraft-dot.tech/mayx/blog
|
https://devcraft-dot.tech/mayx/blog
|
||||||
https://a-t-g.ru/mayx/blog
|
https://a-t-g.ru/mayx/blog
|
||||||
http://qiubei-git.cn/mayx/blog_cn
|
|
||||||
http://wangbeibei.xyz:6002/mayx/blog
|
http://wangbeibei.xyz:6002/mayx/blog
|
||||||
http://8.141.82.163:20000/mayx/blog_cn
|
http://8.141.82.163:20000/mayx/blog_cn
|
||||||
http://81.70.30.91:3000/mayx/blog_cn
|
http://81.70.30.91:3000/mayx/blog_cn
|
||||||
|
|
@ -181,7 +175,6 @@ http://yidaima.cn:6008/mayx/blog_cn
|
||||||
http://8.148.31.14:3000/mayx/blog_cn
|
http://8.148.31.14:3000/mayx/blog_cn
|
||||||
http://58.17.14.95:8001/mayx/blog_cn
|
http://58.17.14.95:8001/mayx/blog_cn
|
||||||
http://39.99.175.172:8000/mayx/blog_cn
|
http://39.99.175.172:8000/mayx/blog_cn
|
||||||
https://git.newnaturalphilosophy.org/mayx/blog_cn
|
|
||||||
https://gitea.detr.top/mayx/blog_cn
|
https://gitea.detr.top/mayx/blog_cn
|
||||||
http://175.178.193.35:3000/mayx/blog_cn
|
http://175.178.193.35:3000/mayx/blog_cn
|
||||||
http://gitea.jb1000.com:88/mayx/blog_cn
|
http://gitea.jb1000.com:88/mayx/blog_cn
|
||||||
|
|
@ -194,15 +187,12 @@ http://jdunlap.com/mayx/blog
|
||||||
https://git.silica.codes/mayx/blog
|
https://git.silica.codes/mayx/blog
|
||||||
https://www.vitelgrid.app/mayx/blog
|
https://www.vitelgrid.app/mayx/blog
|
||||||
https://gitruhub.ru/mayx/blog
|
https://gitruhub.ru/mayx/blog
|
||||||
https://git.linuxposting.xyz/mayx/blog
|
|
||||||
https://git.techworkshop42.ru/mayx/blog
|
https://git.techworkshop42.ru/mayx/blog
|
||||||
http://speedyfox.app/mayx/blog
|
http://speedyfox.app/mayx/blog
|
||||||
https://mjjtop.com/mayx/blog
|
https://mjjtop.com/mayx/blog
|
||||||
https://forgejo.wanderingmonster.dev/mayx/blog
|
https://forgejo.wanderingmonster.dev/mayx/blog
|
||||||
http://v.udvip.com/mayx/blog
|
|
||||||
https://git.edavmig.ru/mayx/blog
|
https://git.edavmig.ru/mayx/blog
|
||||||
https://gitea.ns5001k.sigma2.no/mayx/blog
|
https://gitea.ns5001k.sigma2.no/mayx/blog
|
||||||
https://fzsimo.com/mayx/blog
|
|
||||||
https://git.hemangvyas.com/mayx/blog
|
https://git.hemangvyas.com/mayx/blog
|
||||||
https://gitav.ru/mayx/blog
|
https://gitav.ru/mayx/blog
|
||||||
https://git.sakuzyo.net/mayx/blog
|
https://git.sakuzyo.net/mayx/blog
|
||||||
|
|
@ -210,16 +200,12 @@ http://www.365rise.top/mayx/blog
|
||||||
https://git.ifuntanhub.dev/mayx/blog
|
https://git.ifuntanhub.dev/mayx/blog
|
||||||
https://git.aptcloud.ru/mayx/blog
|
https://git.aptcloud.ru/mayx/blog
|
||||||
https://gitlab.dev.genai-team.ru/mayx/blog
|
https://gitlab.dev.genai-team.ru/mayx/blog
|
||||||
https://d.roxyipt.com/mayx/blog
|
|
||||||
https://git.umervtilte.lol/mayx/blog
|
https://git.umervtilte.lol/mayx/blog
|
||||||
https://git.bitpak.ru/mayx/blog
|
https://git.bitpak.ru/mayx/blog
|
||||||
https://git.amamedis.de/mayx/blog
|
https://git.amamedis.de/mayx/blog
|
||||||
https://git.kunstglass.de/mayx/blog
|
https://git.kunstglass.de/mayx/blog
|
||||||
https://git.kry008.xyz/mayx/blog
|
https://git.kry008.xyz/mayx/blog
|
||||||
https://gitea.onfing.ir/mayx/blog
|
|
||||||
https://gitea.augeo.dev/mayx/blog_cn
|
|
||||||
http://36.213.200.127:23000/mayx/blog_cn
|
http://36.213.200.127:23000/mayx/blog_cn
|
||||||
http://20.219.0.85:3000/mayx/blog_cn
|
|
||||||
https://git.niisse.net/mayx/blog_cn
|
https://git.niisse.net/mayx/blog_cn
|
||||||
https://gitea.yfandxt.asia/mayx/blog_cn
|
https://gitea.yfandxt.asia/mayx/blog_cn
|
||||||
http://81.69.57.215:3000/mayx/blog_cn
|
http://81.69.57.215:3000/mayx/blog_cn
|
||||||
|
|
@ -227,7 +213,6 @@ https://git.dglyoo.com/mayx/blog_cn
|
||||||
http://c8202.top:3000/mayx/blog_cn
|
http://c8202.top:3000/mayx/blog_cn
|
||||||
http://nojava.fun/mayx/blog_cn
|
http://nojava.fun/mayx/blog_cn
|
||||||
https://gitimn.com/mayx/blog
|
https://gitimn.com/mayx/blog
|
||||||
http://git.zapthisblog.com/mayx/blog
|
|
||||||
https://git.resacachile.cl/mayx/blog
|
https://git.resacachile.cl/mayx/blog
|
||||||
https://git.vycsucre.gob.ve/mayx/blog
|
https://git.vycsucre.gob.ve/mayx/blog
|
||||||
https://newtrafficworksgit.online/mayx/blog
|
https://newtrafficworksgit.online/mayx/blog
|
||||||
|
|
@ -236,10 +221,8 @@ https://git.albiobola.nl/mayx/blog
|
||||||
http://gitea.amm.ar/mayx/blog
|
http://gitea.amm.ar/mayx/blog
|
||||||
https://git.83channel.net/mayx/blog
|
https://git.83channel.net/mayx/blog
|
||||||
https://git.zeppone.com/mayx/blog
|
https://git.zeppone.com/mayx/blog
|
||||||
https://git.telecom.quest/mayx/blog
|
|
||||||
https://repo.paperless.rs/mayx/blog
|
https://repo.paperless.rs/mayx/blog
|
||||||
https://urbal.dev/mayx/blog
|
https://urbal.dev/mayx/blog
|
||||||
https://git.pwarde.nl/mayx/blog
|
https://git.pwarde.nl/mayx/blog
|
||||||
https://presko.info/mayx/blog
|
|
||||||
https://bolha.dev/mayx/blog
|
https://bolha.dev/mayx/blog
|
||||||
https://git.checkerwars.com/mayx/blog
|
https://git.checkerwars.com/mayx/blog
|
||||||
|
|
|
||||||
|
|
|
@ -7,12 +7,13 @@ import lzma
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Part 1: 最小 LZMA1 range coder(只做编码)
|
# Part 1: 最小 LZMA1 range coder(只做编码)
|
||||||
#
|
#
|
||||||
# 设计目标:只实现 quine 构造需要的 token:literal / match / rep0-match /
|
# 设计目标:只实现 quine 构造需要的 token:literal / match / rep0-match /
|
||||||
# end-marker,编码字节与历史内容无关(track=False 时不维护输出历史),
|
# end-marker,编码字节与历史内容无关(不维护输出历史),
|
||||||
# 这是"先算结构、后填数据"两阶段装配的基础。
|
# 这是"先算结构、后填数据"两阶段装配的基础。
|
||||||
# 参考:Igor Pavlov 的 LZMA SDK (LzmaEnc.c / LzmaDec.c)。
|
# 参考:Igor Pavlov 的 LZMA SDK (LzmaEnc.c / LzmaDec.c)。
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
@ -125,14 +126,12 @@ def _pos_slot_and_bits(d):
|
||||||
|
|
||||||
|
|
||||||
class LzmaEncoder:
|
class LzmaEncoder:
|
||||||
def __init__(self, lc=3, lp=0, pb=2, track=False):
|
def __init__(self, lc=3, lp=0, pb=2):
|
||||||
"""
|
"""
|
||||||
track=True 时维护输出假历史(literal/match 复制内容),用于一般用途;
|
不维护输出假历史:match 的编码字节只取决于 (dist,len,pos),与历史内容无关,
|
||||||
quine 构造用 track=False:match 的编码字节只取决于 (dist,len,pos),
|
因此 quine 构造(先算结构、后填数据)不需要逐字节复制假历史。
|
||||||
与历史内容无关,可跳过 37MB 级假历史的逐字节复制。
|
|
||||||
"""
|
"""
|
||||||
self.lc, self.lp, self.pb = lc, lp, pb
|
self.lc, self.lp, self.pb = lc, lp, pb
|
||||||
self.track = track
|
|
||||||
self.pos_mask = (1 << pb) - 1
|
self.pos_mask = (1 << pb) - 1
|
||||||
self.lp_mask = (1 << lp) - 1
|
self.lp_mask = (1 << lp) - 1
|
||||||
self.rc = RangeEncoder()
|
self.rc = RangeEncoder()
|
||||||
|
|
@ -184,13 +183,6 @@ class LzmaEncoder:
|
||||||
self.rc.encode_bit(choice, 1, 1)
|
self.rc.encode_bit(choice, 1, 1)
|
||||||
self.rc.bittree_encode(high, 0, kNumHighLenBits, l - kNumMidLenSymbols)
|
self.rc.bittree_encode(high, 0, kNumHighLenBits, l - kNumMidLenSymbols)
|
||||||
|
|
||||||
def _copy_out(self, dist, length):
|
|
||||||
"""track=True 时把 match 的输出复制进假历史。"""
|
|
||||||
src = len(self.out) - dist
|
|
||||||
for i in range(length):
|
|
||||||
self.out.append(self.out[src + i])
|
|
||||||
self.prev_byte = self.out[-1]
|
|
||||||
|
|
||||||
# ---------- 对外 token ----------
|
# ---------- 对外 token ----------
|
||||||
def literal(self, b):
|
def literal(self, b):
|
||||||
if self.state >= kNumLitStates:
|
if self.state >= kNumLitStates:
|
||||||
|
|
@ -240,36 +232,19 @@ class LzmaEncoder:
|
||||||
self.state = 7 if self.state < kNumLitStates else 10
|
self.state = 7 if self.state < kNumLitStates else 10
|
||||||
self.reps[3], self.reps[2], self.reps[1], self.reps[0] = \
|
self.reps[3], self.reps[2], self.reps[1], self.reps[0] = \
|
||||||
self.reps[2], self.reps[1], self.reps[0], d
|
self.reps[2], self.reps[1], self.reps[0], d
|
||||||
if self.track:
|
|
||||||
self._copy_out(dist, length)
|
|
||||||
self.pos += length
|
self.pos += length
|
||||||
|
|
||||||
def rep_match(self, length, rep_idx=0):
|
def rep_match(self, length):
|
||||||
|
"""rep0 匹配:只使用最近一次 match 的距离(quine 构造只需要这种)。"""
|
||||||
assert kMatchMinLen <= length <= 273, length
|
assert kMatchMinLen <= length <= 273, length
|
||||||
ps = self.pos_state
|
ps = self.pos_state
|
||||||
self.rc.encode_bit(self.p_is_match, (self.state << kNumPosBitsMax) + ps, 1)
|
self.rc.encode_bit(self.p_is_match, (self.state << kNumPosBitsMax) + ps, 1)
|
||||||
self.rc.encode_bit(self.p_is_rep, self.state, 1)
|
self.rc.encode_bit(self.p_is_rep, self.state, 1)
|
||||||
if rep_idx == 0:
|
self.rc.encode_bit(self.p_is_rep_g0, self.state, 0)
|
||||||
self.rc.encode_bit(self.p_is_rep_g0, self.state, 0)
|
self.rc.encode_bit(self.p_rep0_long, (self.state << kNumPosBitsMax) + ps, 1)
|
||||||
self.rc.encode_bit(self.p_rep0_long, (self.state << kNumPosBitsMax) + ps, 1)
|
|
||||||
else:
|
|
||||||
self.rc.encode_bit(self.p_is_rep_g0, self.state, 1)
|
|
||||||
if rep_idx == 1:
|
|
||||||
self.rc.encode_bit(self.p_is_rep_g1, self.state, 0)
|
|
||||||
else:
|
|
||||||
self.rc.encode_bit(self.p_is_rep_g1, self.state, 1)
|
|
||||||
self.rc.encode_bit(self.p_is_rep_g2, self.state, 0 if rep_idx == 2 else 1)
|
|
||||||
if rep_idx == 3:
|
|
||||||
self.reps[3] = self.reps[2]
|
|
||||||
self.reps[2] = self.reps[1]
|
|
||||||
self.reps[1] = self.reps[0]
|
|
||||||
self.reps[0] = self.reps[rep_idx]
|
|
||||||
self._encode_len(self.p_rep_len_choice,
|
self._encode_len(self.p_rep_len_choice,
|
||||||
self.p_rep_len_low, self.p_rep_len_mid, self.p_rep_len_high, length)
|
self.p_rep_len_low, self.p_rep_len_mid, self.p_rep_len_high, length)
|
||||||
dist = self.reps[0] + 1
|
|
||||||
self.state = 8 if self.state < kNumLitStates else 11
|
self.state = 8 if self.state < kNumLitStates else 11
|
||||||
if self.track:
|
|
||||||
self._copy_out(dist, length)
|
|
||||||
self.pos += length
|
self.pos += length
|
||||||
|
|
||||||
def end(self):
|
def end(self):
|
||||||
|
|
@ -293,6 +268,8 @@ class LzmaEncoder:
|
||||||
SIG = b"7z\xbc\xaf'\x1c"
|
SIG = b"7z\xbc\xaf'\x1c"
|
||||||
VER = b"\x00\x04"
|
VER = b"\x00\x04"
|
||||||
MAX_MATCH = 273 # LZMA1 单个 match 长度上限
|
MAX_MATCH = 273 # LZMA1 单个 match 长度上限
|
||||||
|
# FILETIME 纪元(1601-01-01)与 Unix 纪元(1970-01-01)之差,单位 100ns
|
||||||
|
FILETIME_EPOCH_OFFSET = 116444736000000000
|
||||||
|
|
||||||
|
|
||||||
def crc32(b, v=0):
|
def crc32(b, v=0):
|
||||||
|
|
@ -356,7 +333,7 @@ def dict_prop_for(maxdist):
|
||||||
|
|
||||||
def lzma_chunk(tokens, out_pos):
|
def lzma_chunk(tokens, out_pos):
|
||||||
"""编一个 LZMA chunk(0xC0: state+props reset,无 dict reset,无 end marker)。
|
"""编一个 LZMA chunk(0xC0: state+props reset,无 dict reset,无 end marker)。
|
||||||
match token 的编码字节只取决于 (dist,len,pos),与历史内容无关(track=False)。"""
|
match token 的编码字节只取决于 (dist,len,pos),与历史内容无关(不维护输出历史)。"""
|
||||||
enc = LzmaEncoder()
|
enc = LzmaEncoder()
|
||||||
enc.pos = out_pos
|
enc.pos = out_pos
|
||||||
total = 0
|
total = 0
|
||||||
|
|
@ -365,7 +342,7 @@ def lzma_chunk(tokens, out_pos):
|
||||||
enc.match(t[1], t[2])
|
enc.match(t[1], t[2])
|
||||||
total += t[2]
|
total += t[2]
|
||||||
else:
|
else:
|
||||||
enc.rep_match(t[1], 0)
|
enc.rep_match(t[1])
|
||||||
total += t[1]
|
total += t[1]
|
||||||
data = enc.finish()
|
data = enc.finish()
|
||||||
assert total - 1 < 65536 and len(data) - 1 < 65536
|
assert total - 1 < 65536 and len(data) - 1 < 65536
|
||||||
|
|
@ -375,28 +352,43 @@ def lzma_chunk(tokens, out_pos):
|
||||||
|
|
||||||
|
|
||||||
class BlogQuine:
|
class BlogQuine:
|
||||||
def __init__(self, root, quine_name="MayxBlog.7z", seed_name="_quine_seed.bin"):
|
def __init__(self, root, quine_name="MayxBlog.7z", seed_name="_quine_seed.bin",
|
||||||
|
src_dir=""):
|
||||||
self.quine_name = quine_name
|
self.quine_name = quine_name
|
||||||
self.seed_name = seed_name
|
self.seed_name = seed_name
|
||||||
|
# 源文件在归档内的前缀目录(如 "src" → 归档内出现 src/hello.txt);"" = 根目录
|
||||||
|
self.src_dir = src_dir.strip("/")
|
||||||
|
# 程序运行时间 → FILETIME(1601-01-01 起 100ns 计数),
|
||||||
|
# 本次运行只取一次,作为归档内所有文件条目的修改时间字段。
|
||||||
|
self.mtime_ft = time.time_ns() // 100 + FILETIME_EPOCH_OFFSET
|
||||||
# walk_entries: walk 顺序(父先子后、同级 dirs 在前)的 (rel, is_dir)。
|
# walk_entries: walk 顺序(父先子后、同级 dirs 在前)的 (rel, is_dir)。
|
||||||
# 子流顺序 = 非空条目在此列表中的顺序,必须自始至终保持同一顺序。
|
# 子流顺序 = 非空条目在此列表中的顺序,必须自始至终保持同一顺序。
|
||||||
self.walk_entries = []
|
self.walk_entries = []
|
||||||
self.files = [] # (relpath, data bytes),顺序 = walk_entries 中文件序
|
self.files = [] # (relpath, data bytes),顺序 = walk_entries 中文件序
|
||||||
|
# src_dir 的各级父目录先作为目录条目挂入(父先子后),
|
||||||
|
# 这样归档结构完整:如 src_dir="public/src" → "public"、"public/src"
|
||||||
|
if self.src_dir:
|
||||||
|
parts = self.src_dir.split("/")
|
||||||
|
for i in range(1, len(parts) + 1):
|
||||||
|
self.walk_entries.append(("/".join(parts[:i]), True))
|
||||||
for dirpath, dirnames, filenames in os.walk(root):
|
for dirpath, dirnames, filenames in os.walk(root):
|
||||||
dirnames.sort()
|
dirnames.sort()
|
||||||
for dn in dirnames:
|
for dn in dirnames:
|
||||||
rel = os.path.relpath(os.path.join(dirpath, dn), root)
|
rel = os.path.relpath(os.path.join(dirpath, dn), root)
|
||||||
self.walk_entries.append((rel.replace(os.sep, "/"), True))
|
self.walk_entries.append((self._prefixed(rel), True))
|
||||||
for fn in sorted(filenames):
|
for fn in sorted(filenames):
|
||||||
p = os.path.join(dirpath, fn)
|
p = os.path.join(dirpath, fn)
|
||||||
rel = os.path.relpath(p, root).replace(os.sep, "/")
|
rel = os.path.relpath(p, root).replace(os.sep, "/")
|
||||||
with open(p, "rb") as fp:
|
with open(p, "rb") as fp:
|
||||||
data = fp.read()
|
data = fp.read()
|
||||||
self.walk_entries.append((rel.replace(os.sep, "/"), False))
|
self.walk_entries.append((self._prefixed(rel), False))
|
||||||
self.files.append((rel.replace(os.sep, "/"), data))
|
self.files.append((self._prefixed(rel), data))
|
||||||
self.dirs = [r for r, isd in self.walk_entries if isd]
|
self.dirs = [r for r, isd in self.walk_entries if isd]
|
||||||
self.content = b"".join(data for _, data in self.files)
|
self.content = b"".join(data for _, data in self.files)
|
||||||
|
|
||||||
|
def _prefixed(self, rel):
|
||||||
|
return self.src_dir + "/" + rel if self.src_dir else rel
|
||||||
|
|
||||||
def entries(self):
|
def entries(self):
|
||||||
ent = [{"name": self.seed_name, "dir": False}]
|
ent = [{"name": self.seed_name, "dir": False}]
|
||||||
ent += [{"name": r, "dir": isd} for r, isd in self.walk_entries]
|
ent += [{"name": r, "dir": isd} for r, isd in self.walk_entries]
|
||||||
|
|
@ -428,6 +420,9 @@ class BlogQuine:
|
||||||
if e["dir"]:
|
if e["dir"]:
|
||||||
bits[i // 8] |= 1 << (7 - i % 8)
|
bits[i // 8] |= 1 << (7 - i % 8)
|
||||||
h += b"\x0e" + varint(len(bits)) + bytes(bits)
|
h += b"\x0e" + varint(len(bits)) + bytes(bits)
|
||||||
|
# kMTime:所有条目(文件与目录)写入修改时间(= 本次程序运行时间)
|
||||||
|
mt = b"\x01\x00" + struct.pack("<Q", self.mtime_ft) * N
|
||||||
|
h += b"\x14" + varint(len(mt)) + mt
|
||||||
names = bytearray(b"\x00") # kName: external=0
|
names = bytearray(b"\x00") # kName: external=0
|
||||||
for e in entries:
|
for e in entries:
|
||||||
names += e["name"].encode("utf-16-le") + b"\x00\x00"
|
names += e["name"].encode("utf-16-le") + b"\x00\x00"
|
||||||
|
|
@ -556,7 +551,7 @@ class BlogQuine:
|
||||||
# ---------- 装配 ----------
|
# ---------- 装配 ----------
|
||||||
def assemble(self, lay):
|
def assemble(self, lay):
|
||||||
F = bytearray(lay["total"])
|
F = bytearray(lay["total"])
|
||||||
d, T, h = lay["d"], lay["T"], lay["h"]
|
d, h = lay["d"], lay["h"]
|
||||||
d_seed = lay["d_seed"]
|
d_seed = lay["d_seed"]
|
||||||
hoff = lay["total"] - h
|
hoff = lay["total"] - h
|
||||||
# pass A: sig + 所有非 payload 字节
|
# pass A: sig + 所有非 payload 字节
|
||||||
|
|
@ -672,7 +667,7 @@ class BlogQuine:
|
||||||
F[p:p + 4] = struct.pack("<I", vals[g])
|
F[p:p + 4] = struct.pack("<I", vals[g])
|
||||||
t = targets()
|
t = targets()
|
||||||
assert t == tuple(vals), "CRC 定点失败: %s != %s" % (t, vals)
|
assert t == tuple(vals), "CRC 定点失败: %s != %s" % (t, vals)
|
||||||
return vals, known
|
return vals
|
||||||
|
|
||||||
def build(self, maxdist_hint=None):
|
def build(self, maxdist_hint=None):
|
||||||
if maxdist_hint is None:
|
if maxdist_hint is None:
|
||||||
|
|
@ -688,15 +683,15 @@ class BlogQuine:
|
||||||
try:
|
try:
|
||||||
lay = self.layout(d_seed, maxdist_hint)
|
lay = self.layout(d_seed, maxdist_hint)
|
||||||
F, seed = self.assemble(lay)
|
F, seed = self.assemble(lay)
|
||||||
crcs, known = self.solve_crc(F, lay, seed)
|
crcs = self.solve_crc(F, lay, seed)
|
||||||
return bytes(F), lay, seed, (crcs, known)
|
return bytes(F), lay, seed, crcs
|
||||||
except (RuntimeError, AssertionError) as e:
|
except (RuntimeError, AssertionError) as e:
|
||||||
last_err = e
|
last_err = e
|
||||||
d_seed += 1
|
d_seed += 1
|
||||||
raise RuntimeError("build 多次失败: %s" % last_err)
|
raise RuntimeError("build 多次失败: %s" % last_err)
|
||||||
|
|
||||||
|
|
||||||
def verify(F, lay, seed, files, quine_name):
|
def verify(F, lay, seed, files):
|
||||||
"""解码 LZMA2 流并逐文件校验。"""
|
"""解码 LZMA2 流并逐文件校验。"""
|
||||||
d, d_seed = lay["d"], lay["d_seed"]
|
d, d_seed = lay["d"], lay["d_seed"]
|
||||||
dec = lzma.LZMADecompressor(
|
dec = lzma.LZMADecompressor(
|
||||||
|
|
@ -729,6 +724,8 @@ def main():
|
||||||
ap.add_argument("--quine-name", default=None,
|
ap.add_argument("--quine-name", default=None,
|
||||||
help="归档内 quine 文件名(默认 = output 的文件名)")
|
help="归档内 quine 文件名(默认 = output 的文件名)")
|
||||||
ap.add_argument("--seed-name", default=".this_is_mayx_blog")
|
ap.add_argument("--seed-name", default=".this_is_mayx_blog")
|
||||||
|
ap.add_argument("--src-dir", default="",
|
||||||
|
help="源文件在归档内的前缀目录(如 src;默认根目录)")
|
||||||
ap.add_argument("--quine-dir", default="",
|
ap.add_argument("--quine-dir", default="",
|
||||||
help="quine 在归档内所在的目录(如 public;默认根目录)")
|
help="quine 在归档内所在的目录(如 public;默认根目录)")
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
|
|
@ -738,16 +735,17 @@ def main():
|
||||||
quine_dir = args.quine_dir.strip("/")
|
quine_dir = args.quine_dir.strip("/")
|
||||||
quine_name = quine_dir + "/" + quine_name
|
quine_name = quine_dir + "/" + quine_name
|
||||||
|
|
||||||
bq = BlogQuine(args.srcdir, quine_name=quine_name, seed_name=args.seed_name)
|
bq = BlogQuine(args.srcdir, quine_name=quine_name, seed_name=args.seed_name,
|
||||||
|
src_dir=args.src_dir)
|
||||||
print("[blogquine] %d 个文件, %d 个目录, 内容 %d 字节"
|
print("[blogquine] %d 个文件, %d 个目录, 内容 %d 字节"
|
||||||
% (len(bq.files), len(bq.dirs), len(bq.content)))
|
% (len(bq.files), len(bq.dirs), len(bq.content)))
|
||||||
F, lay, seed, (crcs, known) = bq.build()
|
F, lay, seed, crcs = bq.build()
|
||||||
with open(args.output, "wb") as fp:
|
with open(args.output, "wb") as fp:
|
||||||
fp.write(F)
|
fp.write(F)
|
||||||
print("[blogquine] written %s: %d 字节 (d=%d, k=%d chunks, n=%d, h=%d, T=%d)"
|
print("[blogquine] written %s: %d 字节 (d=%d, k=%d chunks, n=%d, h=%d, T=%d)"
|
||||||
% (args.output, len(F), lay["d"], lay["k"], lay["n"], lay["h"], lay["T"]))
|
% (args.output, len(F), lay["d"], lay["k"], lay["n"], lay["h"], lay["T"]))
|
||||||
print("[blogquine] CRC 定点: D(quine)=%08x N(hdr)=%08x S(sig)=%08x" % tuple(crcs))
|
print("[blogquine] CRC 定点: D(quine)=%08x N(hdr)=%08x S(sig)=%08x" % tuple(crcs))
|
||||||
ok = verify(F, lay, seed, bq.files, quine_name)
|
ok = verify(F, lay, seed, bq.files)
|
||||||
sys.exit(0 if ok else 1)
|
sys.exit(0 if ok else 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ cd blog
|
||||||
mkdir Mabbs
|
mkdir Mabbs
|
||||||
curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
||||||
bundle exec jekyll build -d ../public_html
|
bundle exec jekyll build -d ../public_html
|
||||||
tar czvf MayxBlog.tgz --exclude-vcs ../public_html/
|
python3 _tools/blogquine.py --src-dir blog --quine-dir blog ../public_html/ MayxBlog.7z
|
||||||
mv MayxBlog.tgz ../public_html/
|
mv MayxBlog.7z ../public_html/
|
||||||
cd ../public_html/
|
cd ../public_html/
|
||||||
unset GIT_DIR
|
unset GIT_DIR
|
||||||
git init
|
git init
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ cd blog
|
||||||
mkdir Mabbs
|
mkdir Mabbs
|
||||||
curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
||||||
bundle exec jekyll build -d ../domains/mayx.serv00.net/public_html/
|
bundle exec jekyll build -d ../domains/mayx.serv00.net/public_html/
|
||||||
tar czvf MayxBlog.tgz --exclude-vcs -C ../domains/mayx.serv00.net public_html/
|
python3 _tools/blogquine.py --src-dir blog --quine-dir blog ../domains/mayx.serv00.net/public_html/ MayxBlog.7z
|
||||||
mv MayxBlog.tgz ../domains/mayx.serv00.net/public_html/
|
mv MayxBlog.7z ../domains/mayx.serv00.net/public_html/
|
||||||
rsync -avz --delete ../domains/mayx.serv00.net/public_html/ mayx@web.sourceforge.net:/home/project-web/mayx/htdocs/
|
rsync -avz --delete ../domains/mayx.serv00.net/public_html/ mayx@web.sourceforge.net:/home/project-web/mayx/htdocs/
|
||||||
cd ../domains/mayx.serv00.net/public_html/
|
cd ../domains/mayx.serv00.net/public_html/
|
||||||
unset GIT_DIR
|
unset GIT_DIR
|
||||||
|
|
@ -18,6 +18,7 @@ git lfs track "*.moc"
|
||||||
git lfs track "*.tgz"
|
git lfs track "*.tgz"
|
||||||
git lfs track "*.jpg"
|
git lfs track "*.jpg"
|
||||||
git lfs track "*.zip"
|
git lfs track "*.zip"
|
||||||
|
git lfs track "*.7z"
|
||||||
git branch -m main
|
git branch -m main
|
||||||
echo "---
|
echo "---
|
||||||
title: Mayx
|
title: Mayx
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
mkdir Mabbs
|
mkdir Mabbs
|
||||||
curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
curl -L -o Mabbs/README.md https://github.com/Mabbs/Mabbs/raw/main/README.md
|
||||||
bundle exec jekyll build -d public
|
bundle exec jekyll build -d public
|
||||||
python3 _tools/blogquine.py public MayxBlog.7z
|
python3 _tools/blogquine.py --src-dir blog --quine-dir blog public MayxBlog.7z
|
||||||
mv MayxBlog.7z public/
|
mv MayxBlog.7z public/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue