allow uploading empty files

This commit is contained in:
ed 2021-10-02 23:34:12 +02:00
parent 63eb08ba9f
commit a6935b0293
3 changed files with 96 additions and 66 deletions

View File

@ -1362,53 +1362,56 @@ class Up2k(object):
# del self.registry[ptop][wark] # del self.registry[ptop][wark]
return ret, dst return ret, dst
# windows cant rename open files # windows cant rename open files
if not ANYWIN or src == dst: if not ANYWIN or src == dst:
self.finish_upload(ptop, wark) self._finish_upload(ptop, wark)
return ret, dst return ret, dst
def finish_upload(self, ptop, wark): def finish_upload(self, ptop, wark):
with self.mutex: with self.mutex:
try: self._finish_upload(ptop, wark)
job = self.registry[ptop][wark]
pdir = os.path.join(job["ptop"], job["prel"])
src = os.path.join(pdir, job["tnam"])
dst = os.path.join(pdir, job["name"])
except Exception as ex:
return "finish_upload, wark, " + repr(ex)
# self.log("--- " + wark + " " + dst + " finish_upload atomic " + dst, 4) def _finish_upload(self, ptop, wark):
atomic_move(src, dst) try:
job = self.registry[ptop][wark]
pdir = os.path.join(job["ptop"], job["prel"])
src = os.path.join(pdir, job["tnam"])
dst = os.path.join(pdir, job["name"])
except Exception as ex:
return "finish_upload, wark, " + repr(ex)
if ANYWIN: # self.log("--- " + wark + " " + dst + " finish_upload atomic " + dst, 4)
a = [dst, job["size"], (int(time.time()), int(job["lmod"]))] atomic_move(src, dst)
self.lastmod_q.put(a)
a = [job[x] for x in "ptop wark prel name lmod size addr".split()] if ANYWIN:
a += [job.get("at") or time.time()] a = [dst, job["size"], (int(time.time()), int(job["lmod"]))]
if self.idx_wark(*a): self.lastmod_q.put(a)
# self.log("pop " + wark + " " + dst + " finish_upload idx_wark", 4)
del self.registry[ptop][wark]
# in-memory registry is reserved for unfinished uploads
dupes = self.dupesched.pop(dst, []) a = [job[x] for x in "ptop wark prel name lmod size addr".split()]
if not dupes: a += [job.get("at") or time.time()]
return if self.idx_wark(*a):
# self.log("pop " + wark + " " + dst + " finish_upload idx_wark", 4)
del self.registry[ptop][wark]
# in-memory registry is reserved for unfinished uploads
cur = self.cur.get(ptop) dupes = self.dupesched.pop(dst, [])
for rd, fn in dupes: if not dupes:
d2 = os.path.join(ptop, rd, fn) return
if os.path.exists(d2):
continue
self._symlink(dst, d2) cur = self.cur.get(ptop)
if cur: for rd, fn in dupes:
self.db_rm(cur, rd, fn) d2 = os.path.join(ptop, rd, fn)
self.db_add(cur, wark, rd, fn, *a[-4:]) if os.path.exists(d2):
continue
self._symlink(dst, d2)
if cur: if cur:
cur.connection.commit() self.db_rm(cur, rd, fn)
self.db_add(cur, wark, rd, fn, *a[-4:])
if cur:
cur.connection.commit()
def idx_wark(self, ptop, wark, rd, fn, lmod, sz, ip, at): def idx_wark(self, ptop, wark, rd, fn, lmod, sz, ip, at):
cur = self.cur.get(ptop) cur = self.cur.get(ptop)
@ -1768,7 +1771,13 @@ class Up2k(object):
except: except:
cj["lmod"] = int(time.time()) cj["lmod"] = int(time.time())
wark = up2k_wark_from_hashlist(self.salt, cj["size"], cj["hash"]) if cj["hash"]:
wark = up2k_wark_from_hashlist(self.salt, cj["size"], cj["hash"])
else:
wark = up2k_wark_from_metadata(
self.salt, cj["size"], cj["lmod"], cj["prel"], cj["name"]
)
return wark return wark
def _hashlist_from_file(self, path): def _hashlist_from_file(self, path):
@ -1811,6 +1820,8 @@ class Up2k(object):
if self.args.nw: if self.args.nw:
job["tnam"] = tnam job["tnam"] = tnam
if not job["hash"]:
del self.registry[job["ptop"]][job["wark"]]
return return
suffix = ".{:.6f}-{}".format(job["t0"], job["addr"]) suffix = ".{:.6f}-{}".format(job["t0"], job["addr"])
@ -1827,8 +1838,12 @@ class Up2k(object):
except: except:
self.log("could not sparse [{}]".format(fp), 3) self.log("could not sparse [{}]".format(fp), 3)
f.seek(job["size"] - 1) if job["hash"]:
f.write(b"e") f.seek(job["size"] - 1)
f.write(b"e")
if not job["hash"]:
self._finish_upload(job["ptop"], job["wark"])
def _lastmodder(self): def _lastmodder(self):
while True: while True:

View File

@ -744,11 +744,14 @@ function up2k_init(subtle) {
more_one_file(); more_one_file();
var bad_files = [], var bad_files = [],
nil_files = [],
good_files = [], good_files = [],
dirs = []; dirs = [];
for (var a = 0; a < files.length; a++) { for (var a = 0; a < files.length; a++) {
var fobj = files[a]; var fobj = files[a],
dst = good_files;
if (is_itemlist) { if (is_itemlist) {
if (fobj.kind !== 'file') if (fobj.kind !== 'file')
continue; continue;
@ -765,16 +768,15 @@ function up2k_init(subtle) {
} }
try { try {
if (fobj.size < 1) if (fobj.size < 1)
throw 1; dst = nil_files;
} }
catch (ex) { catch (ex) {
bad_files.push(fobj.name); dst = bad_files;
continue;
} }
good_files.push([fobj, fobj.name]); dst.push([fobj, fobj.name]);
} }
if (dirs) { if (dirs) {
return read_dirs(null, [], dirs, good_files, bad_files); return read_dirs(null, [], dirs, good_files, nil_files, bad_files);
} }
} }
@ -788,7 +790,7 @@ function up2k_init(subtle) {
} }
var rd_missing_ref = []; var rd_missing_ref = [];
function read_dirs(rd, pf, dirs, good, bad, spins) { function read_dirs(rd, pf, dirs, good, nil, bad, spins) {
spins = spins || 0; spins = spins || 0;
if (++spins == 5) if (++spins == 5)
rd_missing_ref = rd_flatten(pf, dirs); rd_missing_ref = rd_flatten(pf, dirs);
@ -809,7 +811,7 @@ function up2k_init(subtle) {
msg.push('<li>' + esc(missing[a]) + '</li>'); msg.push('<li>' + esc(missing[a]) + '</li>');
return modal.alert(msg.join('') + '</ul>', function () { return modal.alert(msg.join('') + '</ul>', function () {
read_dirs(rd, [], [], good, bad, spins); read_dirs(rd, [], [], good, nil, bad, spins);
}); });
} }
spins = 0; spins = 0;
@ -817,11 +819,11 @@ function up2k_init(subtle) {
if (!dirs.length) { if (!dirs.length) {
if (!pf.length) if (!pf.length)
return gotallfiles(good, bad); return gotallfiles(good, nil, bad);
console.log("retry pf, " + pf.length); console.log("retry pf, " + pf.length);
setTimeout(function () { setTimeout(function () {
read_dirs(rd, pf, dirs, good, bad, spins); read_dirs(rd, pf, dirs, good, nil, bad, spins);
}, 50); }, 50);
return; return;
} }
@ -843,14 +845,15 @@ function up2k_init(subtle) {
pf.push(name); pf.push(name);
dn.file(function (fobj) { dn.file(function (fobj) {
apop(pf, name); apop(pf, name);
var dst = good;
try { try {
if (fobj.size > 0) { if (fobj.size < 1)
good.push([fobj, name]); dst = nil;
return;
}
} }
catch (ex) { } catch (ex) {
bad.push(name); dst = bad;
}
dst.push([fobj, name]);
}); });
} }
ngot += 1; ngot += 1;
@ -859,23 +862,33 @@ function up2k_init(subtle) {
dirs.shift(); dirs.shift();
rd = null; rd = null;
} }
return read_dirs(rd, pf, dirs, good, bad, spins); return read_dirs(rd, pf, dirs, good, nil, bad, spins);
}); });
} }
function gotallfiles(good_files, bad_files) { function gotallfiles(good_files, nil_files, bad_files) {
var ntot = good_files.concat(nil_files, bad_files).length;
if (bad_files.length) { if (bad_files.length) {
var ntot = bad_files.length + good_files.length, var msg = 'These {0} files (of {1} total) were skipped, possibly due to filesystem permissions:\n'.format(bad_files.length, ntot);
msg = 'These {0} files (of {1} total) were skipped because they are empty:\n'.format(bad_files.length, ntot);
for (var a = 0, aa = Math.min(20, bad_files.length); a < aa; a++) for (var a = 0, aa = Math.min(20, bad_files.length); a < aa; a++)
msg += '-- ' + bad_files[a] + '\n'; msg += '-- ' + bad_files[a][1] + '\n';
if (good_files.length - bad_files.length <= 1 && ANDROID)
msg += '\nFirefox-Android has a bug which prevents selecting multiple files. Try selecting one file at a time. For more info, see firefox bug 1456557';
msg += '\nMaybe it works better if you select just one file';
return modal.alert(msg, function () { return modal.alert(msg, function () {
gotallfiles(good_files, []); gotallfiles(good_files, nil_files, []);
});
}
if (nil_files.length) {
var msg = 'These {0} files (of {1} total) are blank/empty; upload them anyways?\n'.format(nil_files.length, ntot);
for (var a = 0, aa = Math.min(20, nil_files.length); a < aa; a++)
msg += '-- ' + nil_files[a][1] + '\n';
msg += '\nMaybe it works better if you select just one file';
return modal.confirm(msg, function () {
gotallfiles(good_files.concat(nil_files), [], []);
}, function () {
gotallfiles(good_files, [], []);
}); });
} }
@ -921,7 +934,7 @@ function up2k_init(subtle) {
"t0": now, "t0": now,
"fobj": fobj, "fobj": fobj,
"name": name, "name": name,
"size": fobj.size, "size": fobj.size || 0,
"lmod": lmod / 1000, "lmod": lmod / 1000,
"purl": fdir, "purl": fdir,
"done": false, "done": false,
@ -946,7 +959,9 @@ function up2k_init(subtle) {
st.bytes.total += fobj.size; st.bytes.total += fobj.size;
st.files.push(entry); st.files.push(entry);
if (uc.turbo) if (!entry.size)
push_t(st.todo.handshake, entry);
else if (uc.turbo)
push_t(st.todo.head, entry); push_t(st.todo.head, entry);
else else
push_t(st.todo.hash, entry); push_t(st.todo.hash, entry);

View File

@ -1049,7 +1049,7 @@ var modal = (function () {
} }
function _confirm(html, cok, cng, fun) { function _confirm(html, cok, cng, fun) {
cb_ok = cok; cb_ok = cok;
cb_ng = cng === undefined ? cok : null; cb_ng = cng === undefined ? cok : cng;
cb_up = fun; cb_up = fun;
html += '<div id="modalb">' + ok_cancel + '</div>'; html += '<div id="modalb">' + ok_cancel + '</div>';
r.show(html); r.show(html);