diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 593104197..fbd4308eb 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -2016,6 +2016,7 @@ def add_db_general(ap, hcores): ap2.add_argument("--no-forget", action="store_true", help="never forget indexed files, even when deleted from disk -- makes it impossible to ever upload the same file twice -- only useful for offloading uploads to a cloud service or something (volflag=noforget)") ap2.add_argument("--forget-ip", metavar="MIN", type=int, default=0, help="remove uploader-IP from database (and make unpost impossible) \033[33mMIN\033[0m minutes after upload, for GDPR reasons. Default [\033[32m0\033[0m] is never-forget. [\033[32m1440\033[0m]=day, [\033[32m10080\033[0m]=week, [\033[32m43200\033[0m]=month. (volflag=forget_ip)") ap2.add_argument("--dbd", metavar="PROFILE", default="wal", help="database durability profile; sets the tradeoff between robustness and speed, see \033[33m--help-dbd\033[0m (volflag=dbd)") + ap2.add_argument("--hist-cow", action="store_true", help="btrfs-only: histpaths (db/thumbs) are nocow by default; if you really need Copy-on-write then enable this (volflag=hist_cow)") ap2.add_argument("--xlink", action="store_true", help="on upload: check all volumes for dupes, not just the target volume (probably buggy, not recommended) (volflag=xlink)") ap2.add_argument("--hash-mt", metavar="CORES", type=int, default=hcores, help="num cpu cores to use for file hashing; set 0 or 1 for single-core hashing") ap2.add_argument("--re-maxage", metavar="SEC", type=int, default=0, help="rescan filesystem for changes every \033[33mSEC\033[0m seconds; 0=off (volflag=scan)") diff --git a/copyparty/cfg.py b/copyparty/cfg.py index 36e6a7a3a..d70b0bd40 100644 --- a/copyparty/cfg.py +++ b/copyparty/cfg.py @@ -52,6 +52,7 @@ def vf_bmap() -> dict[str, str]: "grid", "gsel", "hardlink", + "hist_cow", "magic", "md_no_br", "no_db_ip", @@ -299,6 +300,7 @@ flagcats = { "no_db_ip": "never store uploader-IP in the db; disables unpost", "fat32": "avoid excessive reindexing on android sdcardfs", "dbd=[acid|swal|wal|yolo]": "database speed-durability tradeoff", + "hist_cow": "btrfs: keep copy-on-write enabled on db/thumbs", "xlink": "cross-volume dupe detection / linking (dangerous)", "xdev": "do not descend into other filesystems", "xvol": "do not follow symlinks leaving the volume root", diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 3d0ce4c8f..8bb62d0df 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -52,6 +52,7 @@ from .util import ( ren_open, rmdirs, rmdirs_up, + runcmd, runhook, runihook, s2hms, @@ -1296,6 +1297,14 @@ class Up2k(object): self.log(t % (vpath, ex), 1) return None + if dir_is_empty(self.log_func, not self.args.no_scandir, histpath) and not ( + ANYWIN or UNIX or "hist_cow" in flags + ): + try: + runcmd([b"chattr", b"+C", fsenc(histpath)], 1) + except: + pass + try: cur = self._open_db_wd(db_path) diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 545a4b56c..644ca6bfa 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -1,6 +1,8 @@ #!/bin/bash set -ex +export PRTY_NO_VIPS=1 + if uname | grep -iE '^(msys|mingw)'; then pids=() diff --git a/tests/util.py b/tests/util.py index 3822a556c..f69448557 100644 --- a/tests/util.py +++ b/tests/util.py @@ -148,7 +148,7 @@ class Cfg(Namespace): ex = "allow_flac allow_wav allow_svg_js chpw cookie_lax daw dav_auth dav_mac dav_rt dlni dothidden e2d e2ds e2dsa e2t e2ts e2tsr e2v e2vu e2vp early_ban ed emp exp force_js getmod grid gsel hardlink hardlink_only http_no_tcp ih ihead localtime log_badxml magic md_no_br nid nih no_acode no_athumb no_bauth no_clone no_cp no_dav no_db_ip no_del no_dirsz no_dupe no_dupe_m no_fnugg no_html no_lifetime no_logues no_mime no_mv no_pipe no_poll no_readme no_robots no_sb_md no_sb_lg no_scandir no_script no_tail no_tarcmp no_thumb no_vthumb no_u2abrt no_zip no_zls nrand nsort nw og og_no_head og_s_title ohead opds q rand re_dirsz reflink rm_partial rmagic rss show_hist smb srch_dbg srch_excl srch_nfkc srch_icase stats ui_noacci ui_nocpla ui_noctxb ui_nolbar ui_nombar ui_nonav ui_notree ui_norepl ui_nosrvi uqe usernames vague_403 vc ver vol_nospawn vol_or_crash wo_up_readme wopi write_uplog xdev xlink xvol zipmaxu zs" ka.update(**{k: False for k in ex.split()}) - ex = "dav_inf dedup dotpart dotsrch hook_v no_dhash no_fastboot no_fpool no_htp no_rescan no_sendfile no_ses no_snap no_up_list no_voldump wram re_dhash see_dots plain_ip" + ex = "dav_inf dedup dotpart dotsrch hist_cow hook_v no_dhash no_fastboot no_fpool no_htp no_rescan no_sendfile no_ses no_snap no_up_list no_voldump wram re_dhash see_dots plain_ip" ka.update(**{k: True for k in ex.split()}) ex = "ah_cli ah_gen css_browser dbpath hist ipu js_browser js_other lf_url mime mimes no_forget no_hash no_idx nonsus_urls og_tpl og_ua ua_nodoc ua_nozip"