mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
don't modify untracked files
This commit is contained in:
parent
c2016ba037
commit
53f22c25c9
|
@ -275,7 +275,7 @@ class HttpCli(object):
|
||||||
|
|
||||||
body["vdir"] = self.vpath
|
body["vdir"] = self.vpath
|
||||||
body["rdir"] = os.path.join(vfs.realpath, rem)
|
body["rdir"] = os.path.join(vfs.realpath, rem)
|
||||||
body["addr"] = self.conn.addr[0]
|
body["addr"] = self.addr[0]
|
||||||
|
|
||||||
x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body)
|
x = self.conn.hsrv.broker.put(True, "up2k.handle_json", body)
|
||||||
response = x.get()
|
response = x.get()
|
||||||
|
@ -435,10 +435,12 @@ class HttpCli(object):
|
||||||
if not os.path.isdir(fsenc(fdir)):
|
if not os.path.isdir(fsenc(fdir)):
|
||||||
raise Pebkac(404, "that folder does not exist")
|
raise Pebkac(404, "that folder does not exist")
|
||||||
|
|
||||||
# TODO broker which avoid this race
|
# TODO broker which avoid this race and
|
||||||
# and provides a new filename if taken
|
# provides a new filename if taken (same as up2k)
|
||||||
if os.path.exists(fsenc(fn)):
|
if os.path.exists(fsenc(fn)):
|
||||||
fn += ".{:.6f}".format(time.time())
|
fn += ".{:.6f}-{}".format(time.time(), self.addr[0])
|
||||||
|
# using current-time instead of t0 cause clients
|
||||||
|
# may reuse a name for multiple files in one post
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(fsenc(fn), "wb") as f:
|
with open(fsenc(fn), "wb") as f:
|
||||||
|
|
|
@ -13,7 +13,7 @@ import threading
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
from .__init__ import WINDOWS
|
from .__init__ import WINDOWS
|
||||||
from .util import Pebkac, Queue
|
from .util import Pebkac, Queue, fsenc
|
||||||
|
|
||||||
|
|
||||||
class Up2k(object):
|
class Up2k(object):
|
||||||
|
@ -49,6 +49,7 @@ class Up2k(object):
|
||||||
|
|
||||||
def handle_json(self, cj):
|
def handle_json(self, cj):
|
||||||
wark = self._get_wark(cj)
|
wark = self._get_wark(cj)
|
||||||
|
now = time.time()
|
||||||
with self.mutex:
|
with self.mutex:
|
||||||
# TODO use registry persistence here to symlink any matching wark
|
# TODO use registry persistence here to symlink any matching wark
|
||||||
if wark in self.registry:
|
if wark in self.registry:
|
||||||
|
@ -63,11 +64,16 @@ class Up2k(object):
|
||||||
)
|
)
|
||||||
raise Pebkac(400, err)
|
raise Pebkac(400, err)
|
||||||
else:
|
else:
|
||||||
self._symlink(src, dst)
|
# symlink to the client-provided name,
|
||||||
|
# returning the previous upload info
|
||||||
|
job = deepcopy(job)
|
||||||
|
suffix = self._suffix(dst, now, job["addr"])
|
||||||
|
job["name"] = cj["name"] + suffix
|
||||||
|
self._symlink(src, dst + suffix)
|
||||||
else:
|
else:
|
||||||
job = {
|
job = {
|
||||||
"wark": wark,
|
"wark": wark,
|
||||||
"t0": int(time.time()),
|
"t0": now,
|
||||||
"addr": cj["addr"],
|
"addr": cj["addr"],
|
||||||
"vdir": cj["vdir"],
|
"vdir": cj["vdir"],
|
||||||
"rdir": cj["rdir"],
|
"rdir": cj["rdir"],
|
||||||
|
@ -78,6 +84,9 @@ class Up2k(object):
|
||||||
"hash": deepcopy(cj["hash"]),
|
"hash": deepcopy(cj["hash"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = os.path.join(job["rdir"], job["name"])
|
||||||
|
job["name"] += self._suffix(path, now, cj["addr"])
|
||||||
|
|
||||||
# one chunk may occur multiple times in a file;
|
# one chunk may occur multiple times in a file;
|
||||||
# filter to unique values for the list of missing chunks
|
# filter to unique values for the list of missing chunks
|
||||||
# (preserve order to reduce disk thrashing)
|
# (preserve order to reduce disk thrashing)
|
||||||
|
@ -98,14 +107,22 @@ class Up2k(object):
|
||||||
"wark": wark,
|
"wark": wark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _suffix(self, fpath, ts, ip):
|
||||||
|
# TODO broker which avoid this race and
|
||||||
|
# provides a new filename if taken (same as bup)
|
||||||
|
if not os.path.exists(fsenc(fpath)):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return ".{:.6f}-{}".format(ts, ip)
|
||||||
|
|
||||||
def _symlink(self, src, dst):
|
def _symlink(self, src, dst):
|
||||||
# TODO store this in linktab so we never delete src if there are links to it
|
# TODO store this in linktab so we never delete src if there are links to it
|
||||||
self.log("up2k", "linking dupe:\n {0}\n {1}".format(src, dst))
|
self.log("up2k", "linking dupe:\n {0}\n {1}".format(src, dst))
|
||||||
try:
|
try:
|
||||||
lsrc = src
|
lsrc = src
|
||||||
ldst = dst
|
ldst = dst
|
||||||
fs1 = os.stat(os.path.split(src)[0]).st_dev
|
fs1 = os.stat(fsenc(os.path.split(src)[0])).st_dev
|
||||||
fs2 = os.stat(os.path.split(dst)[0]).st_dev
|
fs2 = os.stat(fsenc(os.path.split(dst)[0])).st_dev
|
||||||
if fs1 == 0:
|
if fs1 == 0:
|
||||||
# py2 on winxp or other unsupported combination
|
# py2 on winxp or other unsupported combination
|
||||||
raise OSError()
|
raise OSError()
|
||||||
|
@ -121,10 +138,10 @@ class Up2k(object):
|
||||||
if nc > 1:
|
if nc > 1:
|
||||||
lsrc = nsrc[nc:]
|
lsrc = nsrc[nc:]
|
||||||
lsrc = "../" * (len(lsrc) - 1) + "/".join(lsrc)
|
lsrc = "../" * (len(lsrc) - 1) + "/".join(lsrc)
|
||||||
os.symlink(lsrc, ldst)
|
os.symlink(fsenc(lsrc), fsenc(ldst))
|
||||||
except (AttributeError, OSError) as ex:
|
except (AttributeError, OSError) as ex:
|
||||||
self.log("up2k", "cannot symlink; creating copy")
|
self.log("up2k", "cannot symlink; creating copy")
|
||||||
shutil.copy2(src, dst)
|
shutil.copy2(fsenc(src), fsenc(dst))
|
||||||
|
|
||||||
def handle_chunk(self, wark, chash):
|
def handle_chunk(self, wark, chash):
|
||||||
with self.mutex:
|
with self.mutex:
|
||||||
|
@ -201,7 +218,7 @@ class Up2k(object):
|
||||||
def _new_upload(self, job):
|
def _new_upload(self, job):
|
||||||
self.registry[job["wark"]] = job
|
self.registry[job["wark"]] = job
|
||||||
path = os.path.join(job["rdir"], job["name"])
|
path = os.path.join(job["rdir"], job["name"])
|
||||||
with open(path, "wb") as f:
|
with open(fsenc(path), "wb") as f:
|
||||||
f.seek(job["size"] - 1)
|
f.seek(job["size"] - 1)
|
||||||
f.write(b"e")
|
f.write(b"e")
|
||||||
|
|
||||||
|
@ -215,6 +232,6 @@ class Up2k(object):
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
for path, times in ready:
|
for path, times in ready:
|
||||||
try:
|
try:
|
||||||
os.utime(path, times)
|
os.utime(fsenc(path), times)
|
||||||
except:
|
except:
|
||||||
self.log("lmod", "failed to utime ({}, {})".format(path, times))
|
self.log("lmod", "failed to utime ({}, {})".format(path, times))
|
||||||
|
|
|
@ -338,7 +338,7 @@ function up2k_init(have_crypto) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var tr = document.createElement('tr');
|
var tr = document.createElement('tr');
|
||||||
tr.innerHTML = '<td></td><td id="f{0}t">hashing</td><td id="f{0}p" class="prog"></td>'.format(st.files.length);
|
tr.innerHTML = '<td id="f{0}n"></td><td id="f{0}t">hashing</td><td id="f{0}p" class="prog"></td>'.format(st.files.length);
|
||||||
tr.getElementsByTagName('td')[0].textContent = entry.name;
|
tr.getElementsByTagName('td')[0].textContent = entry.name;
|
||||||
o('u2tab').appendChild(tr);
|
o('u2tab').appendChild(tr);
|
||||||
|
|
||||||
|
@ -686,6 +686,12 @@ function up2k_init(have_crypto) {
|
||||||
if (xhr.status == 200) {
|
if (xhr.status == 200) {
|
||||||
var response = JSON.parse(xhr.responseText);
|
var response = JSON.parse(xhr.responseText);
|
||||||
|
|
||||||
|
if (response.name !== t.name) {
|
||||||
|
// file exists; server renamed us
|
||||||
|
t.name = response.name;
|
||||||
|
o('f{0}n'.format(t.n)).textContent = t.name;
|
||||||
|
}
|
||||||
|
|
||||||
t.postlist = [];
|
t.postlist = [];
|
||||||
t.wark = response.wark;
|
t.wark = response.wark;
|
||||||
var missing = response.hash;
|
var missing = response.hash;
|
||||||
|
|
Loading…
Reference in a new issue