From fa32e15958b4aaedfb20d016e072b9c93281d940 Mon Sep 17 00:00:00 2001 From: AppleTheGolden Date: Tue, 23 Dec 2025 20:08:29 +0100 Subject: [PATCH] up2k: add "skip if file exists" (#1128) --- copyparty/httpcli.py | 2 +- copyparty/up2k.py | 10 +++++++++- copyparty/web/browser.js | 2 +- copyparty/web/tl/deu.js | 2 +- copyparty/web/up2k.js | 15 +++++++++------ 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 966dd87b..fb00f21e 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -2875,7 +2875,7 @@ class HttpCli(object): body["addr"] = self.ip body["vcfg"] = dbv.flags - if not self.can_delete: + if not self.can_delete and not body.get("replace") == "skip": body.pop("replace", None) if rem: diff --git a/copyparty/up2k.py b/copyparty/up2k.py index f919befe..b8e49d58 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -3468,7 +3468,15 @@ class Up2k(object): fp = djoin(fdir, fname) ow = job.get("replace") and bos.path.exists(fp) - if ow and "mt" in str(job["replace"]).lower(): + if ow: + replace_arg = str(job["replace"]).lower() + + if ow and "skip" in replace_arg: + self.log("skipping upload, filename already exists: %r" % fp) + err = "upload rejected, a file with that name already exists" + raise Pebkac(409, err) + + if ow and "mt" in replace_arg: mts = bos.stat(fp).st_mtime mtc = job["lmod"] if mtc < mts: diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 2881c54c..ec915778 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -158,7 +158,7 @@ if (1) "ul_par": "parallel uploads:", "ut_rand": "randomize filenames", "ut_u2ts": "copy the last-modified timestamp$Nfrom your filesystem to the server\">📅", - "ut_ow": "overwrite existing files on the server?$N🛡️: never (will generate a new filename instead)$N🕒: overwrite if server-file is older than yours$N♻️: always overwrite if the files are different", + "ut_ow": "overwrite existing files on the server?$N🛡️: never (will generate a new filename instead)$N🕒: overwrite if server-file is older than yours$N♻️: always overwrite if the files are different$N⏭️: skip uploading if the server-file exists, regardless of contents", "ut_mt": "continue hashing other files while uploading$N$Nmaybe disable if your CPU or HDD is a bottleneck", "ut_ask": 'ask for confirmation before upload starts">💭', "ut_pot": "improve upload speed on slow devices$Nby making the UI less complex", diff --git a/copyparty/web/tl/deu.js b/copyparty/web/tl/deu.js index 62c4d001..d1052558 100644 --- a/copyparty/web/tl/deu.js +++ b/copyparty/web/tl/deu.js @@ -155,7 +155,7 @@ Ls.deu = { "ul_par": "Parallele Uploads:", "ut_rand": "Zufällige Dateinamen", "ut_u2ts": "Zuletzt geändert-Zeitstempel von$Ndeinem Dateisystem auf den Server übertragen\">📅", - "ut_ow": "Existierende Dateien auf dem Server überschreiben?$N🛡️: Nie (generiert einen neuen Dateinamen)$N🕒: Überschreiben, wenn Server-Datei älter ist als meine$N♻️: Überschreiben, wenn der Dateiinhalt anders ist", + "ut_ow": "Existierende Dateien auf dem Server überschreiben?$N🛡️: Nie (generiert einen neuen Dateinamen)$N🕒: Überschreiben, wenn Server-Datei älter ist als meine$N♻️: Überschreiben, wenn der Dateiinhalt anders ist$N⏭️: Nur hochladen, wenn keine Datei mit dem gleichen Namen existiert", "ut_mt": "Andere Dateien während des Uploads hashen$N$Nsolltest du deaktivieren, falls deine CPU oder Festplatte zum Flaschenhals werden könnte", "ut_ask": 'Vor dem Upload nach Bestätigung fragen">💭', "ut_pot": "Verbessert Upload-Geschwindigkeit$Nindem das UI weniger komplex gemacht wird", diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js index f843431a..418ff31b 100644 --- a/copyparty/web/up2k.js +++ b/copyparty/web/up2k.js @@ -900,19 +900,19 @@ function up2k_init(subtle) { bcfg_bind(uc, 'upnag', 'upnag', false, set_upnag); bcfg_bind(uc, 'upsfx', 'upsfx', false, set_upsfx); - uc.ow = parseInt(sread('u2ow', ['0', '1', '2']) || u2ow); - uc.owt = ['🛡️', '🕒', '♻️']; + uc.ow = parseInt(sread('u2ow', ['0', '1', '2', '3']) || u2ow); + uc.owt = ['🛡️', '🕒', '♻️', '⏭️']; function set_ow() { QS('label[for="u2ow"]').innerHTML = uc.owt[uc.ow]; ebi('u2ow').checked = true; //cosmetic } ebi('u2ow').onclick = function (e) { ev(e); - if (++uc.ow > 2) + if (++uc.ow > 3) uc.ow = 0; swrite('u2ow', uc.ow); set_ow(); - if (uc.ow && !has(perms, 'delete')) + if (uc.ow && uc.ow !== 3 && !has(perms, 'delete')) toast.warn(10, L.u_enoow, 'noow'); else if (toast.tag == 'noow') toast.hide(); @@ -2727,9 +2727,10 @@ function up2k_init(subtle) { var err_pend = rsp.indexOf('partial upload exists at a different') + 1, err_srcb = rsp.indexOf('source file busy; please try again') + 1, err_plug = rsp.indexOf('upload blocked by x') + 1, - err_dupe = rsp.indexOf('upload rejected, file already exists') + 1; + err_dupe = rsp.indexOf('upload rejected, file already exists') + 1, + err_exists = rsp.indexOf('upload rejected, a file with that name already exists') + 1; - if (err_pend || err_srcb || err_plug || err_dupe) { + if (err_pend || err_srcb || err_plug || err_dupe || err_exists) { err = rsp; ofs = err.indexOf('\n/'); if (ofs !== -1) { @@ -2793,6 +2794,8 @@ function up2k_init(subtle) { req.replace = 'mt'; if (uc.ow == 2) req.replace = true; + if (uc.ow == 3) + req.replace = 'skip'; } xhr.open('POST', t.purl, true);