##// END OF EJS Templates
lfs: enable the final download count status message...
Matt Harbison -
r37783:ab04972a default
parent child Browse files
Show More
@@ -1,581 +1,580 b''
1 # blobstore.py - local and remote (speaking Git-LFS protocol) blob storages
1 # blobstore.py - local and remote (speaking Git-LFS protocol) blob storages
2 #
2 #
3 # Copyright 2017 Facebook, Inc.
3 # Copyright 2017 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import hashlib
11 import hashlib
12 import json
12 import json
13 import os
13 import os
14 import re
14 import re
15 import socket
15 import socket
16
16
17 from mercurial.i18n import _
17 from mercurial.i18n import _
18
18
19 from mercurial import (
19 from mercurial import (
20 error,
20 error,
21 pathutil,
21 pathutil,
22 pycompat,
22 pycompat,
23 url as urlmod,
23 url as urlmod,
24 util,
24 util,
25 vfs as vfsmod,
25 vfs as vfsmod,
26 worker,
26 worker,
27 )
27 )
28
28
29 from ..largefiles import lfutil
29 from ..largefiles import lfutil
30
30
31 # 64 bytes for SHA256
31 # 64 bytes for SHA256
32 _lfsre = re.compile(br'\A[a-f0-9]{64}\Z')
32 _lfsre = re.compile(br'\A[a-f0-9]{64}\Z')
33
33
34 class lfsvfs(vfsmod.vfs):
34 class lfsvfs(vfsmod.vfs):
35 def join(self, path):
35 def join(self, path):
36 """split the path at first two characters, like: XX/XXXXX..."""
36 """split the path at first two characters, like: XX/XXXXX..."""
37 if not _lfsre.match(path):
37 if not _lfsre.match(path):
38 raise error.ProgrammingError('unexpected lfs path: %s' % path)
38 raise error.ProgrammingError('unexpected lfs path: %s' % path)
39 return super(lfsvfs, self).join(path[0:2], path[2:])
39 return super(lfsvfs, self).join(path[0:2], path[2:])
40
40
41 def walk(self, path=None, onerror=None):
41 def walk(self, path=None, onerror=None):
42 """Yield (dirpath, [], oids) tuple for blobs under path
42 """Yield (dirpath, [], oids) tuple for blobs under path
43
43
44 Oids only exist in the root of this vfs, so dirpath is always ''.
44 Oids only exist in the root of this vfs, so dirpath is always ''.
45 """
45 """
46 root = os.path.normpath(self.base)
46 root = os.path.normpath(self.base)
47 # when dirpath == root, dirpath[prefixlen:] becomes empty
47 # when dirpath == root, dirpath[prefixlen:] becomes empty
48 # because len(dirpath) < prefixlen.
48 # because len(dirpath) < prefixlen.
49 prefixlen = len(pathutil.normasprefix(root))
49 prefixlen = len(pathutil.normasprefix(root))
50 oids = []
50 oids = []
51
51
52 for dirpath, dirs, files in os.walk(self.reljoin(self.base, path or ''),
52 for dirpath, dirs, files in os.walk(self.reljoin(self.base, path or ''),
53 onerror=onerror):
53 onerror=onerror):
54 dirpath = dirpath[prefixlen:]
54 dirpath = dirpath[prefixlen:]
55
55
56 # Silently skip unexpected files and directories
56 # Silently skip unexpected files and directories
57 if len(dirpath) == 2:
57 if len(dirpath) == 2:
58 oids.extend([dirpath + f for f in files
58 oids.extend([dirpath + f for f in files
59 if _lfsre.match(dirpath + f)])
59 if _lfsre.match(dirpath + f)])
60
60
61 yield ('', [], oids)
61 yield ('', [], oids)
62
62
63 class nullvfs(lfsvfs):
63 class nullvfs(lfsvfs):
64 def __init__(self):
64 def __init__(self):
65 pass
65 pass
66
66
67 def exists(self, oid):
67 def exists(self, oid):
68 return False
68 return False
69
69
70 def read(self, oid):
70 def read(self, oid):
71 # store.read() calls into here if the blob doesn't exist in its
71 # store.read() calls into here if the blob doesn't exist in its
72 # self.vfs. Raise the same error as a normal vfs when asked to read a
72 # self.vfs. Raise the same error as a normal vfs when asked to read a
73 # file that doesn't exist. The only difference is the full file path
73 # file that doesn't exist. The only difference is the full file path
74 # isn't available in the error.
74 # isn't available in the error.
75 raise IOError(errno.ENOENT, '%s: No such file or directory' % oid)
75 raise IOError(errno.ENOENT, '%s: No such file or directory' % oid)
76
76
77 def walk(self, path=None, onerror=None):
77 def walk(self, path=None, onerror=None):
78 return ('', [], [])
78 return ('', [], [])
79
79
80 def write(self, oid, data):
80 def write(self, oid, data):
81 pass
81 pass
82
82
83 class filewithprogress(object):
83 class filewithprogress(object):
84 """a file-like object that supports __len__ and read.
84 """a file-like object that supports __len__ and read.
85
85
86 Useful to provide progress information for how many bytes are read.
86 Useful to provide progress information for how many bytes are read.
87 """
87 """
88
88
89 def __init__(self, fp, callback):
89 def __init__(self, fp, callback):
90 self._fp = fp
90 self._fp = fp
91 self._callback = callback # func(readsize)
91 self._callback = callback # func(readsize)
92 fp.seek(0, os.SEEK_END)
92 fp.seek(0, os.SEEK_END)
93 self._len = fp.tell()
93 self._len = fp.tell()
94 fp.seek(0)
94 fp.seek(0)
95
95
96 def __len__(self):
96 def __len__(self):
97 return self._len
97 return self._len
98
98
99 def read(self, size):
99 def read(self, size):
100 if self._fp is None:
100 if self._fp is None:
101 return b''
101 return b''
102 data = self._fp.read(size)
102 data = self._fp.read(size)
103 if data:
103 if data:
104 if self._callback:
104 if self._callback:
105 self._callback(len(data))
105 self._callback(len(data))
106 else:
106 else:
107 self._fp.close()
107 self._fp.close()
108 self._fp = None
108 self._fp = None
109 return data
109 return data
110
110
111 class local(object):
111 class local(object):
112 """Local blobstore for large file contents.
112 """Local blobstore for large file contents.
113
113
114 This blobstore is used both as a cache and as a staging area for large blobs
114 This blobstore is used both as a cache and as a staging area for large blobs
115 to be uploaded to the remote blobstore.
115 to be uploaded to the remote blobstore.
116 """
116 """
117
117
118 def __init__(self, repo):
118 def __init__(self, repo):
119 fullpath = repo.svfs.join('lfs/objects')
119 fullpath = repo.svfs.join('lfs/objects')
120 self.vfs = lfsvfs(fullpath)
120 self.vfs = lfsvfs(fullpath)
121
121
122 if repo.ui.configbool('experimental', 'lfs.disableusercache'):
122 if repo.ui.configbool('experimental', 'lfs.disableusercache'):
123 self.cachevfs = nullvfs()
123 self.cachevfs = nullvfs()
124 else:
124 else:
125 usercache = lfutil._usercachedir(repo.ui, 'lfs')
125 usercache = lfutil._usercachedir(repo.ui, 'lfs')
126 self.cachevfs = lfsvfs(usercache)
126 self.cachevfs = lfsvfs(usercache)
127 self.ui = repo.ui
127 self.ui = repo.ui
128
128
129 def open(self, oid):
129 def open(self, oid):
130 """Open a read-only file descriptor to the named blob, in either the
130 """Open a read-only file descriptor to the named blob, in either the
131 usercache or the local store."""
131 usercache or the local store."""
132 # The usercache is the most likely place to hold the file. Commit will
132 # The usercache is the most likely place to hold the file. Commit will
133 # write to both it and the local store, as will anything that downloads
133 # write to both it and the local store, as will anything that downloads
134 # the blobs. However, things like clone without an update won't
134 # the blobs. However, things like clone without an update won't
135 # populate the local store. For an init + push of a local clone,
135 # populate the local store. For an init + push of a local clone,
136 # the usercache is the only place it _could_ be. If not present, the
136 # the usercache is the only place it _could_ be. If not present, the
137 # missing file msg here will indicate the local repo, not the usercache.
137 # missing file msg here will indicate the local repo, not the usercache.
138 if self.cachevfs.exists(oid):
138 if self.cachevfs.exists(oid):
139 return self.cachevfs(oid, 'rb')
139 return self.cachevfs(oid, 'rb')
140
140
141 return self.vfs(oid, 'rb')
141 return self.vfs(oid, 'rb')
142
142
143 def download(self, oid, src):
143 def download(self, oid, src):
144 """Read the blob from the remote source in chunks, verify the content,
144 """Read the blob from the remote source in chunks, verify the content,
145 and write to this local blobstore."""
145 and write to this local blobstore."""
146 sha256 = hashlib.sha256()
146 sha256 = hashlib.sha256()
147
147
148 with self.vfs(oid, 'wb', atomictemp=True) as fp:
148 with self.vfs(oid, 'wb', atomictemp=True) as fp:
149 for chunk in util.filechunkiter(src, size=1048576):
149 for chunk in util.filechunkiter(src, size=1048576):
150 fp.write(chunk)
150 fp.write(chunk)
151 sha256.update(chunk)
151 sha256.update(chunk)
152
152
153 realoid = sha256.hexdigest()
153 realoid = sha256.hexdigest()
154 if realoid != oid:
154 if realoid != oid:
155 raise LfsCorruptionError(_('corrupt remote lfs object: %s')
155 raise LfsCorruptionError(_('corrupt remote lfs object: %s')
156 % oid)
156 % oid)
157
157
158 self._linktousercache(oid)
158 self._linktousercache(oid)
159
159
160 def write(self, oid, data):
160 def write(self, oid, data):
161 """Write blob to local blobstore.
161 """Write blob to local blobstore.
162
162
163 This should only be called from the filelog during a commit or similar.
163 This should only be called from the filelog during a commit or similar.
164 As such, there is no need to verify the data. Imports from a remote
164 As such, there is no need to verify the data. Imports from a remote
165 store must use ``download()`` instead."""
165 store must use ``download()`` instead."""
166 with self.vfs(oid, 'wb', atomictemp=True) as fp:
166 with self.vfs(oid, 'wb', atomictemp=True) as fp:
167 fp.write(data)
167 fp.write(data)
168
168
169 self._linktousercache(oid)
169 self._linktousercache(oid)
170
170
171 def _linktousercache(self, oid):
171 def _linktousercache(self, oid):
172 # XXX: should we verify the content of the cache, and hardlink back to
172 # XXX: should we verify the content of the cache, and hardlink back to
173 # the local store on success, but truncate, write and link on failure?
173 # the local store on success, but truncate, write and link on failure?
174 if (not self.cachevfs.exists(oid)
174 if (not self.cachevfs.exists(oid)
175 and not isinstance(self.cachevfs, nullvfs)):
175 and not isinstance(self.cachevfs, nullvfs)):
176 self.ui.note(_('lfs: adding %s to the usercache\n') % oid)
176 self.ui.note(_('lfs: adding %s to the usercache\n') % oid)
177 lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid))
177 lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid))
178
178
179 def read(self, oid, verify=True):
179 def read(self, oid, verify=True):
180 """Read blob from local blobstore."""
180 """Read blob from local blobstore."""
181 if not self.vfs.exists(oid):
181 if not self.vfs.exists(oid):
182 blob = self._read(self.cachevfs, oid, verify)
182 blob = self._read(self.cachevfs, oid, verify)
183
183
184 # Even if revlog will verify the content, it needs to be verified
184 # Even if revlog will verify the content, it needs to be verified
185 # now before making the hardlink to avoid propagating corrupt blobs.
185 # now before making the hardlink to avoid propagating corrupt blobs.
186 # Don't abort if corruption is detected, because `hg verify` will
186 # Don't abort if corruption is detected, because `hg verify` will
187 # give more useful info about the corruption- simply don't add the
187 # give more useful info about the corruption- simply don't add the
188 # hardlink.
188 # hardlink.
189 if verify or hashlib.sha256(blob).hexdigest() == oid:
189 if verify or hashlib.sha256(blob).hexdigest() == oid:
190 self.ui.note(_('lfs: found %s in the usercache\n') % oid)
190 self.ui.note(_('lfs: found %s in the usercache\n') % oid)
191 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid))
191 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid))
192 else:
192 else:
193 self.ui.note(_('lfs: found %s in the local lfs store\n') % oid)
193 self.ui.note(_('lfs: found %s in the local lfs store\n') % oid)
194 blob = self._read(self.vfs, oid, verify)
194 blob = self._read(self.vfs, oid, verify)
195 return blob
195 return blob
196
196
197 def _read(self, vfs, oid, verify):
197 def _read(self, vfs, oid, verify):
198 """Read blob (after verifying) from the given store"""
198 """Read blob (after verifying) from the given store"""
199 blob = vfs.read(oid)
199 blob = vfs.read(oid)
200 if verify:
200 if verify:
201 _verify(oid, blob)
201 _verify(oid, blob)
202 return blob
202 return blob
203
203
204 def verify(self, oid):
204 def verify(self, oid):
205 """Indicate whether or not the hash of the underlying file matches its
205 """Indicate whether or not the hash of the underlying file matches its
206 name."""
206 name."""
207 sha256 = hashlib.sha256()
207 sha256 = hashlib.sha256()
208
208
209 with self.open(oid) as fp:
209 with self.open(oid) as fp:
210 for chunk in util.filechunkiter(fp, size=1048576):
210 for chunk in util.filechunkiter(fp, size=1048576):
211 sha256.update(chunk)
211 sha256.update(chunk)
212
212
213 return oid == sha256.hexdigest()
213 return oid == sha256.hexdigest()
214
214
215 def has(self, oid):
215 def has(self, oid):
216 """Returns True if the local blobstore contains the requested blob,
216 """Returns True if the local blobstore contains the requested blob,
217 False otherwise."""
217 False otherwise."""
218 return self.cachevfs.exists(oid) or self.vfs.exists(oid)
218 return self.cachevfs.exists(oid) or self.vfs.exists(oid)
219
219
220 class _gitlfsremote(object):
220 class _gitlfsremote(object):
221
221
222 def __init__(self, repo, url):
222 def __init__(self, repo, url):
223 ui = repo.ui
223 ui = repo.ui
224 self.ui = ui
224 self.ui = ui
225 baseurl, authinfo = url.authinfo()
225 baseurl, authinfo = url.authinfo()
226 self.baseurl = baseurl.rstrip('/')
226 self.baseurl = baseurl.rstrip('/')
227 useragent = repo.ui.config('experimental', 'lfs.user-agent')
227 useragent = repo.ui.config('experimental', 'lfs.user-agent')
228 if not useragent:
228 if not useragent:
229 useragent = 'git-lfs/2.3.4 (Mercurial %s)' % util.version()
229 useragent = 'git-lfs/2.3.4 (Mercurial %s)' % util.version()
230 self.urlopener = urlmod.opener(ui, authinfo, useragent)
230 self.urlopener = urlmod.opener(ui, authinfo, useragent)
231 self.retry = ui.configint('lfs', 'retry')
231 self.retry = ui.configint('lfs', 'retry')
232
232
233 def writebatch(self, pointers, fromstore):
233 def writebatch(self, pointers, fromstore):
234 """Batch upload from local to remote blobstore."""
234 """Batch upload from local to remote blobstore."""
235 self._batch(_deduplicate(pointers), fromstore, 'upload')
235 self._batch(_deduplicate(pointers), fromstore, 'upload')
236
236
237 def readbatch(self, pointers, tostore):
237 def readbatch(self, pointers, tostore):
238 """Batch download from remote to local blostore."""
238 """Batch download from remote to local blostore."""
239 self._batch(_deduplicate(pointers), tostore, 'download')
239 self._batch(_deduplicate(pointers), tostore, 'download')
240
240
241 def _batchrequest(self, pointers, action):
241 def _batchrequest(self, pointers, action):
242 """Get metadata about objects pointed by pointers for given action
242 """Get metadata about objects pointed by pointers for given action
243
243
244 Return decoded JSON object like {'objects': [{'oid': '', 'size': 1}]}
244 Return decoded JSON object like {'objects': [{'oid': '', 'size': 1}]}
245 See https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
245 See https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
246 """
246 """
247 objects = [{'oid': p.oid(), 'size': p.size()} for p in pointers]
247 objects = [{'oid': p.oid(), 'size': p.size()} for p in pointers]
248 requestdata = json.dumps({
248 requestdata = json.dumps({
249 'objects': objects,
249 'objects': objects,
250 'operation': action,
250 'operation': action,
251 })
251 })
252 batchreq = util.urlreq.request('%s/objects/batch' % self.baseurl,
252 batchreq = util.urlreq.request('%s/objects/batch' % self.baseurl,
253 data=requestdata)
253 data=requestdata)
254 batchreq.add_header('Accept', 'application/vnd.git-lfs+json')
254 batchreq.add_header('Accept', 'application/vnd.git-lfs+json')
255 batchreq.add_header('Content-Type', 'application/vnd.git-lfs+json')
255 batchreq.add_header('Content-Type', 'application/vnd.git-lfs+json')
256 try:
256 try:
257 rsp = self.urlopener.open(batchreq)
257 rsp = self.urlopener.open(batchreq)
258 rawjson = rsp.read()
258 rawjson = rsp.read()
259 except util.urlerr.httperror as ex:
259 except util.urlerr.httperror as ex:
260 raise LfsRemoteError(_('LFS HTTP error: %s (action=%s)')
260 raise LfsRemoteError(_('LFS HTTP error: %s (action=%s)')
261 % (ex, action))
261 % (ex, action))
262 try:
262 try:
263 response = json.loads(rawjson)
263 response = json.loads(rawjson)
264 except ValueError:
264 except ValueError:
265 raise LfsRemoteError(_('LFS server returns invalid JSON: %s')
265 raise LfsRemoteError(_('LFS server returns invalid JSON: %s')
266 % rawjson)
266 % rawjson)
267
267
268 if self.ui.debugflag:
268 if self.ui.debugflag:
269 self.ui.debug('Status: %d\n' % rsp.status)
269 self.ui.debug('Status: %d\n' % rsp.status)
270 # lfs-test-server and hg serve return headers in different order
270 # lfs-test-server and hg serve return headers in different order
271 self.ui.debug('%s\n'
271 self.ui.debug('%s\n'
272 % '\n'.join(sorted(str(rsp.info()).splitlines())))
272 % '\n'.join(sorted(str(rsp.info()).splitlines())))
273
273
274 if 'objects' in response:
274 if 'objects' in response:
275 response['objects'] = sorted(response['objects'],
275 response['objects'] = sorted(response['objects'],
276 key=lambda p: p['oid'])
276 key=lambda p: p['oid'])
277 self.ui.debug('%s\n'
277 self.ui.debug('%s\n'
278 % json.dumps(response, indent=2,
278 % json.dumps(response, indent=2,
279 separators=('', ': '), sort_keys=True))
279 separators=('', ': '), sort_keys=True))
280
280
281 return response
281 return response
282
282
283 def _checkforservererror(self, pointers, responses, action):
283 def _checkforservererror(self, pointers, responses, action):
284 """Scans errors from objects
284 """Scans errors from objects
285
285
286 Raises LfsRemoteError if any objects have an error"""
286 Raises LfsRemoteError if any objects have an error"""
287 for response in responses:
287 for response in responses:
288 # The server should return 404 when objects cannot be found. Some
288 # The server should return 404 when objects cannot be found. Some
289 # server implementation (ex. lfs-test-server) does not set "error"
289 # server implementation (ex. lfs-test-server) does not set "error"
290 # but just removes "download" from "actions". Treat that case
290 # but just removes "download" from "actions". Treat that case
291 # as the same as 404 error.
291 # as the same as 404 error.
292 if 'error' not in response:
292 if 'error' not in response:
293 if (action == 'download'
293 if (action == 'download'
294 and action not in response.get('actions', [])):
294 and action not in response.get('actions', [])):
295 code = 404
295 code = 404
296 else:
296 else:
297 continue
297 continue
298 else:
298 else:
299 # An error dict without a code doesn't make much sense, so
299 # An error dict without a code doesn't make much sense, so
300 # treat as a server error.
300 # treat as a server error.
301 code = response.get('error').get('code', 500)
301 code = response.get('error').get('code', 500)
302
302
303 ptrmap = {p.oid(): p for p in pointers}
303 ptrmap = {p.oid(): p for p in pointers}
304 p = ptrmap.get(response['oid'], None)
304 p = ptrmap.get(response['oid'], None)
305 if p:
305 if p:
306 filename = getattr(p, 'filename', 'unknown')
306 filename = getattr(p, 'filename', 'unknown')
307 errors = {
307 errors = {
308 404: 'The object does not exist',
308 404: 'The object does not exist',
309 410: 'The object was removed by the owner',
309 410: 'The object was removed by the owner',
310 422: 'Validation error',
310 422: 'Validation error',
311 500: 'Internal server error',
311 500: 'Internal server error',
312 }
312 }
313 msg = errors.get(code, 'status code %d' % code)
313 msg = errors.get(code, 'status code %d' % code)
314 raise LfsRemoteError(_('LFS server error for "%s": %s')
314 raise LfsRemoteError(_('LFS server error for "%s": %s')
315 % (filename, msg))
315 % (filename, msg))
316 else:
316 else:
317 raise LfsRemoteError(
317 raise LfsRemoteError(
318 _('LFS server error. Unsolicited response for oid %s')
318 _('LFS server error. Unsolicited response for oid %s')
319 % response['oid'])
319 % response['oid'])
320
320
321 def _extractobjects(self, response, pointers, action):
321 def _extractobjects(self, response, pointers, action):
322 """extract objects from response of the batch API
322 """extract objects from response of the batch API
323
323
324 response: parsed JSON object returned by batch API
324 response: parsed JSON object returned by batch API
325 return response['objects'] filtered by action
325 return response['objects'] filtered by action
326 raise if any object has an error
326 raise if any object has an error
327 """
327 """
328 # Scan errors from objects - fail early
328 # Scan errors from objects - fail early
329 objects = response.get('objects', [])
329 objects = response.get('objects', [])
330 self._checkforservererror(pointers, objects, action)
330 self._checkforservererror(pointers, objects, action)
331
331
332 # Filter objects with given action. Practically, this skips uploading
332 # Filter objects with given action. Practically, this skips uploading
333 # objects which exist in the server.
333 # objects which exist in the server.
334 filteredobjects = [o for o in objects if action in o.get('actions', [])]
334 filteredobjects = [o for o in objects if action in o.get('actions', [])]
335
335
336 return filteredobjects
336 return filteredobjects
337
337
338 def _basictransfer(self, obj, action, localstore):
338 def _basictransfer(self, obj, action, localstore):
339 """Download or upload a single object using basic transfer protocol
339 """Download or upload a single object using basic transfer protocol
340
340
341 obj: dict, an object description returned by batch API
341 obj: dict, an object description returned by batch API
342 action: string, one of ['upload', 'download']
342 action: string, one of ['upload', 'download']
343 localstore: blobstore.local
343 localstore: blobstore.local
344
344
345 See https://github.com/git-lfs/git-lfs/blob/master/docs/api/\
345 See https://github.com/git-lfs/git-lfs/blob/master/docs/api/\
346 basic-transfers.md
346 basic-transfers.md
347 """
347 """
348 oid = pycompat.bytestr(obj['oid'])
348 oid = pycompat.bytestr(obj['oid'])
349
349
350 href = pycompat.bytestr(obj['actions'][action].get('href'))
350 href = pycompat.bytestr(obj['actions'][action].get('href'))
351 headers = obj['actions'][action].get('header', {}).items()
351 headers = obj['actions'][action].get('header', {}).items()
352
352
353 request = util.urlreq.request(href)
353 request = util.urlreq.request(href)
354 if action == 'upload':
354 if action == 'upload':
355 # If uploading blobs, read data from local blobstore.
355 # If uploading blobs, read data from local blobstore.
356 if not localstore.verify(oid):
356 if not localstore.verify(oid):
357 raise error.Abort(_('detected corrupt lfs object: %s') % oid,
357 raise error.Abort(_('detected corrupt lfs object: %s') % oid,
358 hint=_('run hg verify'))
358 hint=_('run hg verify'))
359 request.data = filewithprogress(localstore.open(oid), None)
359 request.data = filewithprogress(localstore.open(oid), None)
360 request.get_method = lambda: 'PUT'
360 request.get_method = lambda: 'PUT'
361 request.add_header('Content-Type', 'application/octet-stream')
361 request.add_header('Content-Type', 'application/octet-stream')
362
362
363 for k, v in headers:
363 for k, v in headers:
364 request.add_header(k, v)
364 request.add_header(k, v)
365
365
366 response = b''
366 response = b''
367 try:
367 try:
368 req = self.urlopener.open(request)
368 req = self.urlopener.open(request)
369
369
370 if self.ui.debugflag:
370 if self.ui.debugflag:
371 self.ui.debug('Status: %d\n' % req.status)
371 self.ui.debug('Status: %d\n' % req.status)
372 # lfs-test-server and hg serve return headers in different order
372 # lfs-test-server and hg serve return headers in different order
373 self.ui.debug('%s\n'
373 self.ui.debug('%s\n'
374 % '\n'.join(sorted(str(req.info()).splitlines())))
374 % '\n'.join(sorted(str(req.info()).splitlines())))
375
375
376 if action == 'download':
376 if action == 'download':
377 # If downloading blobs, store downloaded data to local blobstore
377 # If downloading blobs, store downloaded data to local blobstore
378 localstore.download(oid, req)
378 localstore.download(oid, req)
379 else:
379 else:
380 while True:
380 while True:
381 data = req.read(1048576)
381 data = req.read(1048576)
382 if not data:
382 if not data:
383 break
383 break
384 response += data
384 response += data
385 if response:
385 if response:
386 self.ui.debug('lfs %s response: %s' % (action, response))
386 self.ui.debug('lfs %s response: %s' % (action, response))
387 except util.urlerr.httperror as ex:
387 except util.urlerr.httperror as ex:
388 if self.ui.debugflag:
388 if self.ui.debugflag:
389 self.ui.debug('%s: %s\n' % (oid, ex.read()))
389 self.ui.debug('%s: %s\n' % (oid, ex.read()))
390 raise LfsRemoteError(_('HTTP error: %s (oid=%s, action=%s)')
390 raise LfsRemoteError(_('HTTP error: %s (oid=%s, action=%s)')
391 % (ex, oid, action))
391 % (ex, oid, action))
392
392
393 def _batch(self, pointers, localstore, action):
393 def _batch(self, pointers, localstore, action):
394 if action not in ['upload', 'download']:
394 if action not in ['upload', 'download']:
395 raise error.ProgrammingError('invalid Git-LFS action: %s' % action)
395 raise error.ProgrammingError('invalid Git-LFS action: %s' % action)
396
396
397 response = self._batchrequest(pointers, action)
397 response = self._batchrequest(pointers, action)
398 objects = self._extractobjects(response, pointers, action)
398 objects = self._extractobjects(response, pointers, action)
399 total = sum(x.get('size', 0) for x in objects)
399 total = sum(x.get('size', 0) for x in objects)
400 sizes = {}
400 sizes = {}
401 for obj in objects:
401 for obj in objects:
402 sizes[obj.get('oid')] = obj.get('size', 0)
402 sizes[obj.get('oid')] = obj.get('size', 0)
403 topic = {'upload': _('lfs uploading'),
403 topic = {'upload': _('lfs uploading'),
404 'download': _('lfs downloading')}[action]
404 'download': _('lfs downloading')}[action]
405 if len(objects) > 1:
405 if len(objects) > 1:
406 self.ui.note(_('lfs: need to transfer %d objects (%s)\n')
406 self.ui.note(_('lfs: need to transfer %d objects (%s)\n')
407 % (len(objects), util.bytecount(total)))
407 % (len(objects), util.bytecount(total)))
408 self.ui.progress(topic, 0, total=total)
408 self.ui.progress(topic, 0, total=total)
409 def transfer(chunk):
409 def transfer(chunk):
410 for obj in chunk:
410 for obj in chunk:
411 objsize = obj.get('size', 0)
411 objsize = obj.get('size', 0)
412 if self.ui.verbose:
412 if self.ui.verbose:
413 if action == 'download':
413 if action == 'download':
414 msg = _('lfs: downloading %s (%s)\n')
414 msg = _('lfs: downloading %s (%s)\n')
415 elif action == 'upload':
415 elif action == 'upload':
416 msg = _('lfs: uploading %s (%s)\n')
416 msg = _('lfs: uploading %s (%s)\n')
417 self.ui.note(msg % (obj.get('oid'),
417 self.ui.note(msg % (obj.get('oid'),
418 util.bytecount(objsize)))
418 util.bytecount(objsize)))
419 retry = self.retry
419 retry = self.retry
420 while True:
420 while True:
421 try:
421 try:
422 self._basictransfer(obj, action, localstore)
422 self._basictransfer(obj, action, localstore)
423 yield 1, obj.get('oid')
423 yield 1, obj.get('oid')
424 break
424 break
425 except socket.error as ex:
425 except socket.error as ex:
426 if retry > 0:
426 if retry > 0:
427 self.ui.note(
427 self.ui.note(
428 _('lfs: failed: %r (remaining retry %d)\n')
428 _('lfs: failed: %r (remaining retry %d)\n')
429 % (ex, retry))
429 % (ex, retry))
430 retry -= 1
430 retry -= 1
431 continue
431 continue
432 raise
432 raise
433
433
434 # Until https multiplexing gets sorted out
434 # Until https multiplexing gets sorted out
435 if self.ui.configbool('experimental', 'lfs.worker-enable'):
435 if self.ui.configbool('experimental', 'lfs.worker-enable'):
436 oids = worker.worker(self.ui, 0.1, transfer, (),
436 oids = worker.worker(self.ui, 0.1, transfer, (),
437 sorted(objects, key=lambda o: o.get('oid')))
437 sorted(objects, key=lambda o: o.get('oid')))
438 else:
438 else:
439 oids = transfer(sorted(objects, key=lambda o: o.get('oid')))
439 oids = transfer(sorted(objects, key=lambda o: o.get('oid')))
440
440
441 processed = 0
441 processed = 0
442 blobs = 0
442 blobs = 0
443 for _one, oid in oids:
443 for _one, oid in oids:
444 processed += sizes[oid]
444 processed += sizes[oid]
445 blobs += 1
445 blobs += 1
446 self.ui.progress(topic, processed, total=total)
446 self.ui.progress(topic, processed, total=total)
447 self.ui.note(_('lfs: processed: %s\n') % oid)
447 self.ui.note(_('lfs: processed: %s\n') % oid)
448 self.ui.progress(topic, pos=None, total=total)
448 self.ui.progress(topic, pos=None, total=total)
449
449
450 if blobs > 0:
450 if blobs > 0:
451 if action == 'upload':
451 if action == 'upload':
452 self.ui.status(_('lfs: uploaded %d files (%s)\n')
452 self.ui.status(_('lfs: uploaded %d files (%s)\n')
453 % (blobs, util.bytecount(processed)))
453 % (blobs, util.bytecount(processed)))
454 # TODO: coalesce the download requests, and comment this in
454 elif action == 'download':
455 #elif action == 'download':
455 self.ui.status(_('lfs: downloaded %d files (%s)\n')
456 # self.ui.status(_('lfs: downloaded %d files (%s)\n')
456 % (blobs, util.bytecount(processed)))
457 # % (blobs, util.bytecount(processed)))
458
457
459 def __del__(self):
458 def __del__(self):
460 # copied from mercurial/httppeer.py
459 # copied from mercurial/httppeer.py
461 urlopener = getattr(self, 'urlopener', None)
460 urlopener = getattr(self, 'urlopener', None)
462 if urlopener:
461 if urlopener:
463 for h in urlopener.handlers:
462 for h in urlopener.handlers:
464 h.close()
463 h.close()
465 getattr(h, "close_all", lambda : None)()
464 getattr(h, "close_all", lambda : None)()
466
465
467 class _dummyremote(object):
466 class _dummyremote(object):
468 """Dummy store storing blobs to temp directory."""
467 """Dummy store storing blobs to temp directory."""
469
468
470 def __init__(self, repo, url):
469 def __init__(self, repo, url):
471 fullpath = repo.vfs.join('lfs', url.path)
470 fullpath = repo.vfs.join('lfs', url.path)
472 self.vfs = lfsvfs(fullpath)
471 self.vfs = lfsvfs(fullpath)
473
472
474 def writebatch(self, pointers, fromstore):
473 def writebatch(self, pointers, fromstore):
475 for p in _deduplicate(pointers):
474 for p in _deduplicate(pointers):
476 content = fromstore.read(p.oid(), verify=True)
475 content = fromstore.read(p.oid(), verify=True)
477 with self.vfs(p.oid(), 'wb', atomictemp=True) as fp:
476 with self.vfs(p.oid(), 'wb', atomictemp=True) as fp:
478 fp.write(content)
477 fp.write(content)
479
478
480 def readbatch(self, pointers, tostore):
479 def readbatch(self, pointers, tostore):
481 for p in _deduplicate(pointers):
480 for p in _deduplicate(pointers):
482 with self.vfs(p.oid(), 'rb') as fp:
481 with self.vfs(p.oid(), 'rb') as fp:
483 tostore.download(p.oid(), fp)
482 tostore.download(p.oid(), fp)
484
483
485 class _nullremote(object):
484 class _nullremote(object):
486 """Null store storing blobs to /dev/null."""
485 """Null store storing blobs to /dev/null."""
487
486
488 def __init__(self, repo, url):
487 def __init__(self, repo, url):
489 pass
488 pass
490
489
491 def writebatch(self, pointers, fromstore):
490 def writebatch(self, pointers, fromstore):
492 pass
491 pass
493
492
494 def readbatch(self, pointers, tostore):
493 def readbatch(self, pointers, tostore):
495 pass
494 pass
496
495
497 class _promptremote(object):
496 class _promptremote(object):
498 """Prompt user to set lfs.url when accessed."""
497 """Prompt user to set lfs.url when accessed."""
499
498
500 def __init__(self, repo, url):
499 def __init__(self, repo, url):
501 pass
500 pass
502
501
503 def writebatch(self, pointers, fromstore, ui=None):
502 def writebatch(self, pointers, fromstore, ui=None):
504 self._prompt()
503 self._prompt()
505
504
506 def readbatch(self, pointers, tostore, ui=None):
505 def readbatch(self, pointers, tostore, ui=None):
507 self._prompt()
506 self._prompt()
508
507
509 def _prompt(self):
508 def _prompt(self):
510 raise error.Abort(_('lfs.url needs to be configured'))
509 raise error.Abort(_('lfs.url needs to be configured'))
511
510
512 _storemap = {
511 _storemap = {
513 'https': _gitlfsremote,
512 'https': _gitlfsremote,
514 'http': _gitlfsremote,
513 'http': _gitlfsremote,
515 'file': _dummyremote,
514 'file': _dummyremote,
516 'null': _nullremote,
515 'null': _nullremote,
517 None: _promptremote,
516 None: _promptremote,
518 }
517 }
519
518
520 def _deduplicate(pointers):
519 def _deduplicate(pointers):
521 """Remove any duplicate oids that exist in the list"""
520 """Remove any duplicate oids that exist in the list"""
522 reduced = util.sortdict()
521 reduced = util.sortdict()
523 for p in pointers:
522 for p in pointers:
524 reduced[p.oid()] = p
523 reduced[p.oid()] = p
525 return reduced.values()
524 return reduced.values()
526
525
527 def _verify(oid, content):
526 def _verify(oid, content):
528 realoid = hashlib.sha256(content).hexdigest()
527 realoid = hashlib.sha256(content).hexdigest()
529 if realoid != oid:
528 if realoid != oid:
530 raise LfsCorruptionError(_('detected corrupt lfs object: %s') % oid,
529 raise LfsCorruptionError(_('detected corrupt lfs object: %s') % oid,
531 hint=_('run hg verify'))
530 hint=_('run hg verify'))
532
531
533 def remote(repo, remote=None):
532 def remote(repo, remote=None):
534 """remotestore factory. return a store in _storemap depending on config
533 """remotestore factory. return a store in _storemap depending on config
535
534
536 If ``lfs.url`` is specified, use that remote endpoint. Otherwise, try to
535 If ``lfs.url`` is specified, use that remote endpoint. Otherwise, try to
537 infer the endpoint, based on the remote repository using the same path
536 infer the endpoint, based on the remote repository using the same path
538 adjustments as git. As an extension, 'http' is supported as well so that
537 adjustments as git. As an extension, 'http' is supported as well so that
539 ``hg serve`` works out of the box.
538 ``hg serve`` works out of the box.
540
539
541 https://github.com/git-lfs/git-lfs/blob/master/docs/api/server-discovery.md
540 https://github.com/git-lfs/git-lfs/blob/master/docs/api/server-discovery.md
542 """
541 """
543 lfsurl = repo.ui.config('lfs', 'url')
542 lfsurl = repo.ui.config('lfs', 'url')
544 url = util.url(lfsurl or '')
543 url = util.url(lfsurl or '')
545 if lfsurl is None:
544 if lfsurl is None:
546 if remote:
545 if remote:
547 path = remote
546 path = remote
548 elif util.safehasattr(repo, '_subtoppath'):
547 elif util.safehasattr(repo, '_subtoppath'):
549 # The pull command sets this during the optional update phase, which
548 # The pull command sets this during the optional update phase, which
550 # tells exactly where the pull originated, whether 'paths.default'
549 # tells exactly where the pull originated, whether 'paths.default'
551 # or explicit.
550 # or explicit.
552 path = repo._subtoppath
551 path = repo._subtoppath
553 else:
552 else:
554 # TODO: investigate 'paths.remote:lfsurl' style path customization,
553 # TODO: investigate 'paths.remote:lfsurl' style path customization,
555 # and fall back to inferring from 'paths.remote' if unspecified.
554 # and fall back to inferring from 'paths.remote' if unspecified.
556 path = repo.ui.config('paths', 'default') or ''
555 path = repo.ui.config('paths', 'default') or ''
557
556
558 defaulturl = util.url(path)
557 defaulturl = util.url(path)
559
558
560 # TODO: support local paths as well.
559 # TODO: support local paths as well.
561 # TODO: consider the ssh -> https transformation that git applies
560 # TODO: consider the ssh -> https transformation that git applies
562 if defaulturl.scheme in (b'http', b'https'):
561 if defaulturl.scheme in (b'http', b'https'):
563 if defaulturl.path and defaulturl.path[:-1] != b'/':
562 if defaulturl.path and defaulturl.path[:-1] != b'/':
564 defaulturl.path += b'/'
563 defaulturl.path += b'/'
565 defaulturl.path = (defaulturl.path or b'') + b'.git/info/lfs'
564 defaulturl.path = (defaulturl.path or b'') + b'.git/info/lfs'
566
565
567 url = util.url(bytes(defaulturl))
566 url = util.url(bytes(defaulturl))
568 repo.ui.note(_('lfs: assuming remote store: %s\n') % url)
567 repo.ui.note(_('lfs: assuming remote store: %s\n') % url)
569
568
570 scheme = url.scheme
569 scheme = url.scheme
571 if scheme not in _storemap:
570 if scheme not in _storemap:
572 raise error.Abort(_('lfs: unknown url scheme: %s') % scheme)
571 raise error.Abort(_('lfs: unknown url scheme: %s') % scheme)
573 return _storemap[scheme](repo, url)
572 return _storemap[scheme](repo, url)
574
573
575 class LfsRemoteError(error.RevlogError):
574 class LfsRemoteError(error.RevlogError):
576 pass
575 pass
577
576
578 class LfsCorruptionError(error.Abort):
577 class LfsCorruptionError(error.Abort):
579 """Raised when a corrupt blob is detected, aborting an operation
578 """Raised when a corrupt blob is detected, aborting an operation
580
579
581 It exists to allow specialized handling on the server side."""
580 It exists to allow specialized handling on the server side."""
@@ -1,332 +1,333 b''
1 #require serve no-reposimplestore
1 #require serve no-reposimplestore
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > lfs=
5 > lfs=
6 > [lfs]
6 > [lfs]
7 > track=all()
7 > track=all()
8 > [web]
8 > [web]
9 > push_ssl = False
9 > push_ssl = False
10 > allow-push = *
10 > allow-push = *
11 > EOF
11 > EOF
12
12
13 Serving LFS files can experimentally be turned off. The long term solution is
13 Serving LFS files can experimentally be turned off. The long term solution is
14 to support the 'verify' action in both client and server, so that the server can
14 to support the 'verify' action in both client and server, so that the server can
15 tell the client to store files elsewhere.
15 tell the client to store files elsewhere.
16
16
17 $ hg init server
17 $ hg init server
18 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
18 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
19 > --config experimental.lfs.serve=False -R server serve -d \
19 > --config experimental.lfs.serve=False -R server serve -d \
20 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
20 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
21 $ cat hg.pid >> $DAEMON_PIDS
21 $ cat hg.pid >> $DAEMON_PIDS
22
22
23 Uploads fail...
23 Uploads fail...
24
24
25 $ hg init client
25 $ hg init client
26 $ echo 'this-is-an-lfs-file' > client/lfs.bin
26 $ echo 'this-is-an-lfs-file' > client/lfs.bin
27 $ hg -R client ci -Am 'initial commit'
27 $ hg -R client ci -Am 'initial commit'
28 adding lfs.bin
28 adding lfs.bin
29 $ hg -R client push http://localhost:$HGPORT
29 $ hg -R client push http://localhost:$HGPORT
30 pushing to http://localhost:$HGPORT/
30 pushing to http://localhost:$HGPORT/
31 searching for changes
31 searching for changes
32 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=upload)!
32 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=upload)!
33 [255]
33 [255]
34
34
35 ... so do a local push to make the data available. Remove the blob from the
35 ... so do a local push to make the data available. Remove the blob from the
36 default cache, so it attempts to download.
36 default cache, so it attempts to download.
37 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
37 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
38 > --config "lfs.url=null://" \
38 > --config "lfs.url=null://" \
39 > -R client push -q server
39 > -R client push -q server
40 $ mv `hg config lfs.usercache` $TESTTMP/servercache
40 $ mv `hg config lfs.usercache` $TESTTMP/servercache
41
41
42 Downloads fail...
42 Downloads fail...
43
43
44 $ hg clone http://localhost:$HGPORT httpclone
44 $ hg clone http://localhost:$HGPORT httpclone
45 requesting all changes
45 requesting all changes
46 adding changesets
46 adding changesets
47 adding manifests
47 adding manifests
48 adding file changes
48 adding file changes
49 added 1 changesets with 1 changes to 1 files
49 added 1 changesets with 1 changes to 1 files
50 new changesets 525251863cad
50 new changesets 525251863cad
51 updating to branch default
51 updating to branch default
52 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
52 abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
53 [255]
53 [255]
54
54
55 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
55 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
56
56
57 $ cat $TESTTMP/access.log $TESTTMP/errors.log
57 $ cat $TESTTMP/access.log $TESTTMP/errors.log
58 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
58 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
59 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
59 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
60 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
60 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
61 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
61 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
62 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
62 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
63 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
63 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
64 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
64 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
65 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
65 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
66 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
66 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
67
67
68 Blob URIs are correct when --prefix is used
68 Blob URIs are correct when --prefix is used
69
69
70 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
70 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
71 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
71 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
72 > -p $HGPORT --pid-file=hg.pid --prefix=subdir/mount/point \
72 > -p $HGPORT --pid-file=hg.pid --prefix=subdir/mount/point \
73 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
73 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
74 $ cat hg.pid >> $DAEMON_PIDS
74 $ cat hg.pid >> $DAEMON_PIDS
75
75
76 $ hg clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
76 $ hg clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
77 using http://localhost:$HGPORT/subdir/mount/point
77 using http://localhost:$HGPORT/subdir/mount/point
78 sending capabilities command
78 sending capabilities command
79 query 1; heads
79 query 1; heads
80 sending batch command
80 sending batch command
81 requesting all changes
81 requesting all changes
82 sending getbundle command
82 sending getbundle command
83 bundle2-input-bundle: with-transaction
83 bundle2-input-bundle: with-transaction
84 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
84 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
85 adding changesets
85 adding changesets
86 add changeset 525251863cad
86 add changeset 525251863cad
87 adding manifests
87 adding manifests
88 adding file changes
88 adding file changes
89 adding lfs.bin revisions
89 adding lfs.bin revisions
90 added 1 changesets with 1 changes to 1 files
90 added 1 changesets with 1 changes to 1 files
91 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
91 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
92 bundle2-input-part: total payload size 648
92 bundle2-input-part: total payload size 648
93 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
93 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
94 bundle2-input-part: "phase-heads" supported
94 bundle2-input-part: "phase-heads" supported
95 bundle2-input-part: total payload size 24
95 bundle2-input-part: total payload size 24
96 bundle2-input-part: "cache:rev-branch-cache" supported
96 bundle2-input-part: "cache:rev-branch-cache" supported
97 bundle2-input-part: total payload size 39
97 bundle2-input-part: total payload size 39
98 bundle2-input-bundle: 3 parts total
98 bundle2-input-bundle: 3 parts total
99 checking for updated bookmarks
99 checking for updated bookmarks
100 updating the branch cache
100 updating the branch cache
101 new changesets 525251863cad
101 new changesets 525251863cad
102 updating to branch default
102 updating to branch default
103 resolving manifests
103 resolving manifests
104 branchmerge: False, force: False, partial: False
104 branchmerge: False, force: False, partial: False
105 ancestor: 000000000000, local: 000000000000+, remote: 525251863cad
105 ancestor: 000000000000, local: 000000000000+, remote: 525251863cad
106 lfs: assuming remote store: http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs
106 lfs: assuming remote store: http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs
107 Status: 200
107 Status: 200
108 Content-Length: 371
108 Content-Length: 371
109 Content-Type: application/vnd.git-lfs+json
109 Content-Type: application/vnd.git-lfs+json
110 Date: $HTTP_DATE$
110 Date: $HTTP_DATE$
111 Server: testing stub value
111 Server: testing stub value
112 {
112 {
113 "objects": [
113 "objects": [
114 {
114 {
115 "actions": {
115 "actions": {
116 "download": {
116 "download": {
117 "expires_at": "$ISO_8601_DATE_TIME$"
117 "expires_at": "$ISO_8601_DATE_TIME$"
118 "header": {
118 "header": {
119 "Accept": "application/vnd.git-lfs"
119 "Accept": "application/vnd.git-lfs"
120 }
120 }
121 "href": "http://localhost:$HGPORT/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
121 "href": "http://localhost:$HGPORT/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
122 }
122 }
123 }
123 }
124 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
124 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
125 "size": 20
125 "size": 20
126 }
126 }
127 ]
127 ]
128 "transfer": "basic"
128 "transfer": "basic"
129 }
129 }
130 lfs: downloading f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e (20 bytes)
130 lfs: downloading f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e (20 bytes)
131 Status: 200
131 Status: 200
132 Content-Length: 20
132 Content-Length: 20
133 Content-Type: application/octet-stream
133 Content-Type: application/octet-stream
134 Date: $HTTP_DATE$
134 Date: $HTTP_DATE$
135 Server: testing stub value
135 Server: testing stub value
136 lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
136 lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
137 lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
137 lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
138 lfs: downloaded 1 files (20 bytes)
138 lfs.bin: remote created -> g
139 lfs.bin: remote created -> g
139 getting lfs.bin
140 getting lfs.bin
140 lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
141 lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142
143
143 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
144 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
144
145
145 $ cat $TESTTMP/access.log $TESTTMP/errors.log
146 $ cat $TESTTMP/access.log $TESTTMP/errors.log
146 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
147 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
147 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
148 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
148 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
149 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
149 $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
150 $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
150 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
151 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
151
152
152 $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
153 $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
153 > import errno
154 > import errno
154 > from hgext.lfs import blobstore
155 > from hgext.lfs import blobstore
155 >
156 >
156 > _numverifies = 0
157 > _numverifies = 0
157 > _readerr = True
158 > _readerr = True
158 >
159 >
159 > def reposetup(ui, repo):
160 > def reposetup(ui, repo):
160 > # Nothing to do with a remote repo
161 > # Nothing to do with a remote repo
161 > if not repo.local():
162 > if not repo.local():
162 > return
163 > return
163 >
164 >
164 > store = repo.svfs.lfslocalblobstore
165 > store = repo.svfs.lfslocalblobstore
165 > class badstore(store.__class__):
166 > class badstore(store.__class__):
166 > def download(self, oid, src):
167 > def download(self, oid, src):
167 > '''Called in the server to handle reading from the client in a
168 > '''Called in the server to handle reading from the client in a
168 > PUT request.'''
169 > PUT request.'''
169 > origread = src.read
170 > origread = src.read
170 > def _badread(nbytes):
171 > def _badread(nbytes):
171 > # Simulate bad data/checksum failure from the client
172 > # Simulate bad data/checksum failure from the client
172 > return b'0' * len(origread(nbytes))
173 > return b'0' * len(origread(nbytes))
173 > src.read = _badread
174 > src.read = _badread
174 > super(badstore, self).download(oid, src)
175 > super(badstore, self).download(oid, src)
175 >
176 >
176 > def _read(self, vfs, oid, verify):
177 > def _read(self, vfs, oid, verify):
177 > '''Called in the server to read data for a GET request, and then
178 > '''Called in the server to read data for a GET request, and then
178 > calls self._verify() on it before returning.'''
179 > calls self._verify() on it before returning.'''
179 > global _readerr
180 > global _readerr
180 > # One time simulation of a read error
181 > # One time simulation of a read error
181 > if _readerr:
182 > if _readerr:
182 > _readerr = False
183 > _readerr = False
183 > raise IOError(errno.EIO, '%s: I/O error' % oid)
184 > raise IOError(errno.EIO, '%s: I/O error' % oid)
184 > # Simulate corrupt content on client download
185 > # Simulate corrupt content on client download
185 > blobstore._verify(oid, 'dummy content')
186 > blobstore._verify(oid, 'dummy content')
186 >
187 >
187 > def verify(self, oid):
188 > def verify(self, oid):
188 > '''Called in the server to populate the Batch API response,
189 > '''Called in the server to populate the Batch API response,
189 > letting the client re-upload if the file is corrupt.'''
190 > letting the client re-upload if the file is corrupt.'''
190 > # Fail verify in Batch API for one clone command and one push
191 > # Fail verify in Batch API for one clone command and one push
191 > # command with an IOError. Then let it through to access other
192 > # command with an IOError. Then let it through to access other
192 > # functions. Checksum failure is tested elsewhere.
193 > # functions. Checksum failure is tested elsewhere.
193 > global _numverifies
194 > global _numverifies
194 > _numverifies += 1
195 > _numverifies += 1
195 > if _numverifies <= 2:
196 > if _numverifies <= 2:
196 > raise IOError(errno.EIO, '%s: I/O error' % oid)
197 > raise IOError(errno.EIO, '%s: I/O error' % oid)
197 > return super(badstore, self).verify(oid)
198 > return super(badstore, self).verify(oid)
198 >
199 >
199 > store.__class__ = badstore
200 > store.__class__ = badstore
200 > EOF
201 > EOF
201
202
202 $ rm -rf `hg config lfs.usercache`
203 $ rm -rf `hg config lfs.usercache`
203 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
204 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
204 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
205 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
205 > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
206 > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
206 > -R server serve -d \
207 > -R server serve -d \
207 > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
208 > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
208 $ cat hg.pid >> $DAEMON_PIDS
209 $ cat hg.pid >> $DAEMON_PIDS
209
210
210 Test an I/O error in localstore.verify() (Batch API) with GET
211 Test an I/O error in localstore.verify() (Batch API) with GET
211
212
212 $ hg clone http://localhost:$HGPORT1 httpclone2
213 $ hg clone http://localhost:$HGPORT1 httpclone2
213 requesting all changes
214 requesting all changes
214 adding changesets
215 adding changesets
215 adding manifests
216 adding manifests
216 adding file changes
217 adding file changes
217 added 1 changesets with 1 changes to 1 files
218 added 1 changesets with 1 changes to 1 files
218 new changesets 525251863cad
219 new changesets 525251863cad
219 updating to branch default
220 updating to branch default
220 abort: LFS server error for "lfs.bin": Internal server error!
221 abort: LFS server error for "lfs.bin": Internal server error!
221 [255]
222 [255]
222
223
223 Test an I/O error in localstore.verify() (Batch API) with PUT
224 Test an I/O error in localstore.verify() (Batch API) with PUT
224
225
225 $ echo foo > client/lfs.bin
226 $ echo foo > client/lfs.bin
226 $ hg -R client ci -m 'mod lfs'
227 $ hg -R client ci -m 'mod lfs'
227 $ hg -R client push http://localhost:$HGPORT1
228 $ hg -R client push http://localhost:$HGPORT1
228 pushing to http://localhost:$HGPORT1/
229 pushing to http://localhost:$HGPORT1/
229 searching for changes
230 searching for changes
230 abort: LFS server error for "unknown": Internal server error!
231 abort: LFS server error for "unknown": Internal server error!
231 [255]
232 [255]
232 TODO: figure out how to associate the file name in the error above
233 TODO: figure out how to associate the file name in the error above
233
234
234 Test a bad checksum sent by the client in the transfer API
235 Test a bad checksum sent by the client in the transfer API
235
236
236 $ hg -R client push http://localhost:$HGPORT1
237 $ hg -R client push http://localhost:$HGPORT1
237 pushing to http://localhost:$HGPORT1/
238 pushing to http://localhost:$HGPORT1/
238 searching for changes
239 searching for changes
239 abort: HTTP error: HTTP Error 422: corrupt blob (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)!
240 abort: HTTP error: HTTP Error 422: corrupt blob (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)!
240 [255]
241 [255]
241
242
242 $ echo 'test lfs file' > server/lfs3.bin
243 $ echo 'test lfs file' > server/lfs3.bin
243 $ hg --config experimental.lfs.disableusercache=True \
244 $ hg --config experimental.lfs.disableusercache=True \
244 > -R server ci -Aqm 'another lfs file'
245 > -R server ci -Aqm 'another lfs file'
245 $ hg -R client pull -q http://localhost:$HGPORT1
246 $ hg -R client pull -q http://localhost:$HGPORT1
246
247
247 Test an I/O error during the processing of the GET request
248 Test an I/O error during the processing of the GET request
248
249
249 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
250 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
250 > -R client update -r tip
251 > -R client update -r tip
251 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
252 abort: HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
252 [255]
253 [255]
253
254
254 Test a checksum failure during the processing of the GET request
255 Test a checksum failure during the processing of the GET request
255
256
256 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
257 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
257 > -R client update -r tip
258 > -R client update -r tip
258 abort: HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
259 abort: HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
259 [255]
260 [255]
260
261
261 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
262 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
262
263
263 $ cat $TESTTMP/access.log
264 $ cat $TESTTMP/access.log
264 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
265 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
265 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
266 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
266 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
267 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
267 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
268 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
268 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
269 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
269 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
270 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
270 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
271 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
271 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
272 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
272 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
273 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
273 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
274 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
274 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
275 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
275 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
276 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
276 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
277 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
277 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
278 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
278 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
279 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
279 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
280 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
280 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
281 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
281 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
282 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
282 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 422 - (glob)
283 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 422 - (glob)
283 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
284 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
284 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
285 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
285 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
286 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
286 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
287 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
287 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
288 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
288 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
289 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
289 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 422 - (glob)
290 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 422 - (glob)
290
291
291 $ grep -v ' File "' $TESTTMP/errors.log
292 $ grep -v ' File "' $TESTTMP/errors.log
292 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
293 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
293 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
294 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
294 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
295 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
295 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
296 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
296 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e: I/O error (glob)
297 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e: I/O error (glob)
297 $LOCALIP - - [$ERRDATE$] HG error: (glob)
298 $LOCALIP - - [$ERRDATE$] HG error: (glob)
298 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
299 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
299 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
300 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
300 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
301 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
301 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
302 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, '%s: I/O error' % oid) (glob)
302 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c: I/O error (glob)
303 $LOCALIP - - [$ERRDATE$] HG error: IOError: [Errno 5] b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c: I/O error (glob)
303 $LOCALIP - - [$ERRDATE$] HG error: (glob)
304 $LOCALIP - - [$ERRDATE$] HG error: (glob)
304 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
305 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
305 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
306 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
306 $LOCALIP - - [$ERRDATE$] HG error: localstore.download(oid, req.bodyfh) (glob)
307 $LOCALIP - - [$ERRDATE$] HG error: localstore.download(oid, req.bodyfh) (glob)
307 $LOCALIP - - [$ERRDATE$] HG error: super(badstore, self).download(oid, src) (glob)
308 $LOCALIP - - [$ERRDATE$] HG error: super(badstore, self).download(oid, src) (glob)
308 $LOCALIP - - [$ERRDATE$] HG error: % oid) (glob)
309 $LOCALIP - - [$ERRDATE$] HG error: % oid) (glob)
309 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (glob)
310 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (glob)
310 $LOCALIP - - [$ERRDATE$] HG error: (glob)
311 $LOCALIP - - [$ERRDATE$] HG error: (glob)
311 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
312 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
312 Traceback (most recent call last):
313 Traceback (most recent call last):
313 self.do_write()
314 self.do_write()
314 self.do_hgweb()
315 self.do_hgweb()
315 for chunk in self.server.application(env, self._start_response):
316 for chunk in self.server.application(env, self._start_response):
316 for r in self._runwsgi(req, res, repo):
317 for r in self._runwsgi(req, res, repo):
317 rctx, req, res, self.check_perm)
318 rctx, req, res, self.check_perm)
318 return func(*(args + a), **kw)
319 return func(*(args + a), **kw)
319 lambda perm:
320 lambda perm:
320 res.setbodybytes(localstore.read(oid))
321 res.setbodybytes(localstore.read(oid))
321 blob = self._read(self.vfs, oid, verify)
322 blob = self._read(self.vfs, oid, verify)
322 raise IOError(errno.EIO, '%s: I/O error' % oid)
323 raise IOError(errno.EIO, '%s: I/O error' % oid)
323 IOError: [Errno 5] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error
324 IOError: [Errno 5] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error
324
325
325 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
326 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
326 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
327 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
327 $LOCALIP - - [$ERRDATE$] HG error: res.setbodybytes(localstore.read(oid)) (glob)
328 $LOCALIP - - [$ERRDATE$] HG error: res.setbodybytes(localstore.read(oid)) (glob)
328 $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob)
329 $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob)
329 $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, 'dummy content') (glob)
330 $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, 'dummy content') (glob)
330 $LOCALIP - - [$ERRDATE$] HG error: hint=_('run hg verify')) (glob)
331 $LOCALIP - - [$ERRDATE$] HG error: hint=_('run hg verify')) (glob)
331 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (glob)
332 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (glob)
332 $LOCALIP - - [$ERRDATE$] HG error: (glob)
333 $LOCALIP - - [$ERRDATE$] HG error: (glob)
@@ -1,445 +1,450 b''
1 #testcases lfsremote-on lfsremote-off
1 #testcases lfsremote-on lfsremote-off
2 #require serve no-reposimplestore
2 #require serve no-reposimplestore
3
3
4 This test splits `hg serve` with and without using the extension into separate
4 This test splits `hg serve` with and without using the extension into separate
5 tests cases. The tests are broken down as follows, where "LFS"/"No-LFS"
5 tests cases. The tests are broken down as follows, where "LFS"/"No-LFS"
6 indicates whether or not there are commits that use an LFS file, and "D"/"E"
6 indicates whether or not there are commits that use an LFS file, and "D"/"E"
7 indicates whether or not the extension is loaded. The "X" cases are not tested
7 indicates whether or not the extension is loaded. The "X" cases are not tested
8 individually, because the lfs requirement causes the process to bail early if
8 individually, because the lfs requirement causes the process to bail early if
9 the extension is disabled.
9 the extension is disabled.
10
10
11 . Server
11 . Server
12 .
12 .
13 . No-LFS LFS
13 . No-LFS LFS
14 . +----------------------------+
14 . +----------------------------+
15 . | || D | E | D | E |
15 . | || D | E | D | E |
16 . |---++=======================|
16 . |---++=======================|
17 . C | D || N/A | #1 | X | #4 |
17 . C | D || N/A | #1 | X | #4 |
18 . l No +---++-----------------------|
18 . l No +---++-----------------------|
19 . i LFS | E || #2 | #2 | X | #5 |
19 . i LFS | E || #2 | #2 | X | #5 |
20 . e +---++-----------------------|
20 . e +---++-----------------------|
21 . n | D || X | X | X | X |
21 . n | D || X | X | X | X |
22 . t LFS |---++-----------------------|
22 . t LFS |---++-----------------------|
23 . | E || #3 | #3 | X | #6 |
23 . | E || #3 | #3 | X | #6 |
24 . |---++-----------------------+
24 . |---++-----------------------+
25
25
26 $ hg init server
26 $ hg init server
27 $ SERVER_REQUIRES="$TESTTMP/server/.hg/requires"
27 $ SERVER_REQUIRES="$TESTTMP/server/.hg/requires"
28
28
29 Skip the experimental.changegroup3=True config. Failure to agree on this comes
29 Skip the experimental.changegroup3=True config. Failure to agree on this comes
30 first, and causes a "ValueError: no common changegroup version" or "abort:
30 first, and causes a "ValueError: no common changegroup version" or "abort:
31 HTTP Error 500: Internal Server Error", if the extension is only loaded on one
31 HTTP Error 500: Internal Server Error", if the extension is only loaded on one
32 side. If that *is* enabled, the subsequent failure is "abort: missing processor
32 side. If that *is* enabled, the subsequent failure is "abort: missing processor
33 for flag '0x2000'!" if the extension is only loaded on one side (possibly also
33 for flag '0x2000'!" if the extension is only loaded on one side (possibly also
34 masked by the Internal Server Error message).
34 masked by the Internal Server Error message).
35 $ cat >> $HGRCPATH <<EOF
35 $ cat >> $HGRCPATH <<EOF
36 > [experimental]
36 > [experimental]
37 > lfs.disableusercache = True
37 > lfs.disableusercache = True
38 > [lfs]
38 > [lfs]
39 > threshold=10
39 > threshold=10
40 > [web]
40 > [web]
41 > allow_push=*
41 > allow_push=*
42 > push_ssl=False
42 > push_ssl=False
43 > EOF
43 > EOF
44
44
45 #if lfsremote-on
45 #if lfsremote-on
46 $ hg --config extensions.lfs= -R server \
46 $ hg --config extensions.lfs= -R server \
47 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
47 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
48 #else
48 #else
49 $ hg --config extensions.lfs=! -R server \
49 $ hg --config extensions.lfs=! -R server \
50 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
50 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
51 #endif
51 #endif
52
52
53 $ cat hg.pid >> $DAEMON_PIDS
53 $ cat hg.pid >> $DAEMON_PIDS
54 $ hg clone -q http://localhost:$HGPORT client
54 $ hg clone -q http://localhost:$HGPORT client
55 $ grep 'lfs' client/.hg/requires $SERVER_REQUIRES
55 $ grep 'lfs' client/.hg/requires $SERVER_REQUIRES
56 [1]
56 [1]
57
57
58 --------------------------------------------------------------------------------
58 --------------------------------------------------------------------------------
59 Case #1: client with non-lfs content and the extension disabled; server with
59 Case #1: client with non-lfs content and the extension disabled; server with
60 non-lfs content, and the extension enabled.
60 non-lfs content, and the extension enabled.
61
61
62 $ cd client
62 $ cd client
63 $ echo 'non-lfs' > nonlfs.txt
63 $ echo 'non-lfs' > nonlfs.txt
64 $ hg ci -Aqm 'non-lfs'
64 $ hg ci -Aqm 'non-lfs'
65 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
65 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
66 [1]
66 [1]
67
67
68 #if lfsremote-on
68 #if lfsremote-on
69
69
70 $ hg push -q
70 $ hg push -q
71 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
71 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
72 [1]
72 [1]
73
73
74 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client1_clone
74 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client1_clone
75 $ grep 'lfs' $TESTTMP/client1_clone/.hg/requires $SERVER_REQUIRES
75 $ grep 'lfs' $TESTTMP/client1_clone/.hg/requires $SERVER_REQUIRES
76 [1]
76 [1]
77
77
78 $ hg init $TESTTMP/client1_pull
78 $ hg init $TESTTMP/client1_pull
79 $ hg -R $TESTTMP/client1_pull pull -q http://localhost:$HGPORT
79 $ hg -R $TESTTMP/client1_pull pull -q http://localhost:$HGPORT
80 $ grep 'lfs' $TESTTMP/client1_pull/.hg/requires $SERVER_REQUIRES
80 $ grep 'lfs' $TESTTMP/client1_pull/.hg/requires $SERVER_REQUIRES
81 [1]
81 [1]
82
82
83 $ hg identify http://localhost:$HGPORT
83 $ hg identify http://localhost:$HGPORT
84 d437e1d24fbd
84 d437e1d24fbd
85
85
86 #endif
86 #endif
87
87
88 --------------------------------------------------------------------------------
88 --------------------------------------------------------------------------------
89 Case #2: client with non-lfs content and the extension enabled; server with
89 Case #2: client with non-lfs content and the extension enabled; server with
90 non-lfs content, and the extension state controlled by #testcases.
90 non-lfs content, and the extension state controlled by #testcases.
91
91
92 $ cat >> $HGRCPATH <<EOF
92 $ cat >> $HGRCPATH <<EOF
93 > [extensions]
93 > [extensions]
94 > lfs =
94 > lfs =
95 > EOF
95 > EOF
96 $ echo 'non-lfs' > nonlfs2.txt
96 $ echo 'non-lfs' > nonlfs2.txt
97 $ hg ci -Aqm 'non-lfs file with lfs client'
97 $ hg ci -Aqm 'non-lfs file with lfs client'
98
98
99 Since no lfs content has been added yet, the push is allowed, even when the
99 Since no lfs content has been added yet, the push is allowed, even when the
100 extension is not enabled remotely.
100 extension is not enabled remotely.
101
101
102 $ hg push -q
102 $ hg push -q
103 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
103 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
104 [1]
104 [1]
105
105
106 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client2_clone
106 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client2_clone
107 $ grep 'lfs' $TESTTMP/client2_clone/.hg/requires $SERVER_REQUIRES
107 $ grep 'lfs' $TESTTMP/client2_clone/.hg/requires $SERVER_REQUIRES
108 [1]
108 [1]
109
109
110 $ hg init $TESTTMP/client2_pull
110 $ hg init $TESTTMP/client2_pull
111 $ hg -R $TESTTMP/client2_pull pull -q http://localhost:$HGPORT
111 $ hg -R $TESTTMP/client2_pull pull -q http://localhost:$HGPORT
112 $ grep 'lfs' $TESTTMP/client2_pull/.hg/requires $SERVER_REQUIRES
112 $ grep 'lfs' $TESTTMP/client2_pull/.hg/requires $SERVER_REQUIRES
113 [1]
113 [1]
114
114
115 $ hg identify http://localhost:$HGPORT
115 $ hg identify http://localhost:$HGPORT
116 1477875038c6
116 1477875038c6
117
117
118 --------------------------------------------------------------------------------
118 --------------------------------------------------------------------------------
119 Case #3: client with lfs content and the extension enabled; server with
119 Case #3: client with lfs content and the extension enabled; server with
120 non-lfs content, and the extension state controlled by #testcases. The server
120 non-lfs content, and the extension state controlled by #testcases. The server
121 should have an 'lfs' requirement after it picks up its first commit with a blob.
121 should have an 'lfs' requirement after it picks up its first commit with a blob.
122
122
123 $ echo 'this is a big lfs file' > lfs.bin
123 $ echo 'this is a big lfs file' > lfs.bin
124 $ hg ci -Aqm 'lfs'
124 $ hg ci -Aqm 'lfs'
125 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
125 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
126 .hg/requires:lfs
126 .hg/requires:lfs
127
127
128 #if lfsremote-off
128 #if lfsremote-off
129 $ hg push -q
129 $ hg push -q
130 abort: required features are not supported in the destination: lfs
130 abort: required features are not supported in the destination: lfs
131 (enable the lfs extension on the server)
131 (enable the lfs extension on the server)
132 [255]
132 [255]
133 #else
133 #else
134 $ hg push -q
134 $ hg push -q
135 #endif
135 #endif
136 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
136 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
137 .hg/requires:lfs
137 .hg/requires:lfs
138 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
138 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
139
139
140 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client3_clone
140 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client3_clone
141 $ grep 'lfs' $TESTTMP/client3_clone/.hg/requires $SERVER_REQUIRES || true
141 $ grep 'lfs' $TESTTMP/client3_clone/.hg/requires $SERVER_REQUIRES || true
142 $TESTTMP/client3_clone/.hg/requires:lfs (lfsremote-on !)
142 $TESTTMP/client3_clone/.hg/requires:lfs (lfsremote-on !)
143 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
143 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
144
144
145 $ hg init $TESTTMP/client3_pull
145 $ hg init $TESTTMP/client3_pull
146 $ hg -R $TESTTMP/client3_pull pull -q http://localhost:$HGPORT
146 $ hg -R $TESTTMP/client3_pull pull -q http://localhost:$HGPORT
147 $ grep 'lfs' $TESTTMP/client3_pull/.hg/requires $SERVER_REQUIRES || true
147 $ grep 'lfs' $TESTTMP/client3_pull/.hg/requires $SERVER_REQUIRES || true
148 $TESTTMP/client3_pull/.hg/requires:lfs (lfsremote-on !)
148 $TESTTMP/client3_pull/.hg/requires:lfs (lfsremote-on !)
149 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
149 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
150
150
151 The difference here is the push failed above when the extension isn't
151 The difference here is the push failed above when the extension isn't
152 enabled on the server.
152 enabled on the server.
153 $ hg identify http://localhost:$HGPORT
153 $ hg identify http://localhost:$HGPORT
154 8374dc4052cb (lfsremote-on !)
154 8374dc4052cb (lfsremote-on !)
155 1477875038c6 (lfsremote-off !)
155 1477875038c6 (lfsremote-off !)
156
156
157 Don't bother testing the lfsremote-off cases- the server won't be able
157 Don't bother testing the lfsremote-off cases- the server won't be able
158 to launch if there's lfs content and the extension is disabled.
158 to launch if there's lfs content and the extension is disabled.
159
159
160 #if lfsremote-on
160 #if lfsremote-on
161
161
162 --------------------------------------------------------------------------------
162 --------------------------------------------------------------------------------
163 Case #4: client with non-lfs content and the extension disabled; server with
163 Case #4: client with non-lfs content and the extension disabled; server with
164 lfs content, and the extension enabled.
164 lfs content, and the extension enabled.
165
165
166 $ cat >> $HGRCPATH <<EOF
166 $ cat >> $HGRCPATH <<EOF
167 > [extensions]
167 > [extensions]
168 > lfs = !
168 > lfs = !
169 > EOF
169 > EOF
170
170
171 $ hg init $TESTTMP/client4
171 $ hg init $TESTTMP/client4
172 $ cd $TESTTMP/client4
172 $ cd $TESTTMP/client4
173 $ cat >> .hg/hgrc <<EOF
173 $ cat >> .hg/hgrc <<EOF
174 > [paths]
174 > [paths]
175 > default = http://localhost:$HGPORT
175 > default = http://localhost:$HGPORT
176 > EOF
176 > EOF
177 $ echo 'non-lfs' > nonlfs2.txt
177 $ echo 'non-lfs' > nonlfs2.txt
178 $ hg ci -Aqm 'non-lfs'
178 $ hg ci -Aqm 'non-lfs'
179 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
179 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
180 $TESTTMP/server/.hg/requires:lfs
180 $TESTTMP/server/.hg/requires:lfs
181
181
182 $ hg push -q --force
182 $ hg push -q --force
183 warning: repository is unrelated
183 warning: repository is unrelated
184 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
184 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
185 $TESTTMP/server/.hg/requires:lfs
185 $TESTTMP/server/.hg/requires:lfs
186
186
187 TODO: fail more gracefully.
187 TODO: fail more gracefully.
188
188
189 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client4_clone
189 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client4_clone
190 abort: HTTP Error 500: Internal Server Error
190 abort: HTTP Error 500: Internal Server Error
191 [255]
191 [255]
192 $ grep 'lfs' $TESTTMP/client4_clone/.hg/requires $SERVER_REQUIRES
192 $ grep 'lfs' $TESTTMP/client4_clone/.hg/requires $SERVER_REQUIRES
193 grep: $TESTTMP/client4_clone/.hg/requires: $ENOENT$
193 grep: $TESTTMP/client4_clone/.hg/requires: $ENOENT$
194 $TESTTMP/server/.hg/requires:lfs
194 $TESTTMP/server/.hg/requires:lfs
195 [2]
195 [2]
196
196
197 TODO: fail more gracefully.
197 TODO: fail more gracefully.
198
198
199 $ hg init $TESTTMP/client4_pull
199 $ hg init $TESTTMP/client4_pull
200 $ hg -R $TESTTMP/client4_pull pull -q http://localhost:$HGPORT
200 $ hg -R $TESTTMP/client4_pull pull -q http://localhost:$HGPORT
201 abort: HTTP Error 500: Internal Server Error
201 abort: HTTP Error 500: Internal Server Error
202 [255]
202 [255]
203 $ grep 'lfs' $TESTTMP/client4_pull/.hg/requires $SERVER_REQUIRES
203 $ grep 'lfs' $TESTTMP/client4_pull/.hg/requires $SERVER_REQUIRES
204 $TESTTMP/server/.hg/requires:lfs
204 $TESTTMP/server/.hg/requires:lfs
205
205
206 $ hg identify http://localhost:$HGPORT
206 $ hg identify http://localhost:$HGPORT
207 03b080fa9d93
207 03b080fa9d93
208
208
209 --------------------------------------------------------------------------------
209 --------------------------------------------------------------------------------
210 Case #5: client with non-lfs content and the extension enabled; server with
210 Case #5: client with non-lfs content and the extension enabled; server with
211 lfs content, and the extension enabled.
211 lfs content, and the extension enabled.
212
212
213 $ cat >> $HGRCPATH <<EOF
213 $ cat >> $HGRCPATH <<EOF
214 > [extensions]
214 > [extensions]
215 > lfs =
215 > lfs =
216 > EOF
216 > EOF
217 $ echo 'non-lfs' > nonlfs3.txt
217 $ echo 'non-lfs' > nonlfs3.txt
218 $ hg ci -Aqm 'non-lfs file with lfs client'
218 $ hg ci -Aqm 'non-lfs file with lfs client'
219
219
220 $ hg push -q
220 $ hg push -q
221 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
221 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
222 $TESTTMP/server/.hg/requires:lfs
222 $TESTTMP/server/.hg/requires:lfs
223
223
224 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client5_clone
224 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client5_clone
225 $ grep 'lfs' $TESTTMP/client5_clone/.hg/requires $SERVER_REQUIRES
225 $ grep 'lfs' $TESTTMP/client5_clone/.hg/requires $SERVER_REQUIRES
226 $TESTTMP/client5_clone/.hg/requires:lfs
226 $TESTTMP/client5_clone/.hg/requires:lfs
227 $TESTTMP/server/.hg/requires:lfs
227 $TESTTMP/server/.hg/requires:lfs
228
228
229 $ hg init $TESTTMP/client5_pull
229 $ hg init $TESTTMP/client5_pull
230 $ hg -R $TESTTMP/client5_pull pull -q http://localhost:$HGPORT
230 $ hg -R $TESTTMP/client5_pull pull -q http://localhost:$HGPORT
231 $ grep 'lfs' $TESTTMP/client5_pull/.hg/requires $SERVER_REQUIRES
231 $ grep 'lfs' $TESTTMP/client5_pull/.hg/requires $SERVER_REQUIRES
232 $TESTTMP/client5_pull/.hg/requires:lfs
232 $TESTTMP/client5_pull/.hg/requires:lfs
233 $TESTTMP/server/.hg/requires:lfs
233 $TESTTMP/server/.hg/requires:lfs
234
234
235 $ hg identify http://localhost:$HGPORT
235 $ hg identify http://localhost:$HGPORT
236 c729025cc5e3
236 c729025cc5e3
237
237
238 --------------------------------------------------------------------------------
238 --------------------------------------------------------------------------------
239 Case #6: client with lfs content and the extension enabled; server with
239 Case #6: client with lfs content and the extension enabled; server with
240 lfs content, and the extension enabled.
240 lfs content, and the extension enabled.
241
241
242 $ echo 'this is another lfs file' > lfs2.txt
242 $ echo 'this is another lfs file' > lfs2.txt
243 $ hg ci -Aqm 'lfs file with lfs client'
243 $ hg ci -Aqm 'lfs file with lfs client'
244
244
245 $ hg --config paths.default= push -v http://localhost:$HGPORT
245 $ hg --config paths.default= push -v http://localhost:$HGPORT
246 pushing to http://localhost:$HGPORT/
246 pushing to http://localhost:$HGPORT/
247 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
247 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
248 searching for changes
248 searching for changes
249 remote has heads on branch 'default' that are not known locally: 8374dc4052cb
249 remote has heads on branch 'default' that are not known locally: 8374dc4052cb
250 lfs: uploading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
250 lfs: uploading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
251 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
251 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
252 lfs: uploaded 1 files (25 bytes)
252 lfs: uploaded 1 files (25 bytes)
253 1 changesets found
253 1 changesets found
254 uncompressed size of bundle content:
254 uncompressed size of bundle content:
255 206 (changelog)
255 206 (changelog)
256 172 (manifests)
256 172 (manifests)
257 275 lfs2.txt
257 275 lfs2.txt
258 remote: adding changesets
258 remote: adding changesets
259 remote: adding manifests
259 remote: adding manifests
260 remote: adding file changes
260 remote: adding file changes
261 remote: added 1 changesets with 1 changes to 1 files
261 remote: added 1 changesets with 1 changes to 1 files
262 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
262 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
263 .hg/requires:lfs
263 .hg/requires:lfs
264 $TESTTMP/server/.hg/requires:lfs
264 $TESTTMP/server/.hg/requires:lfs
265
265
266 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client6_clone
266 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client6_clone
267 $ grep 'lfs' $TESTTMP/client6_clone/.hg/requires $SERVER_REQUIRES
267 $ grep 'lfs' $TESTTMP/client6_clone/.hg/requires $SERVER_REQUIRES
268 $TESTTMP/client6_clone/.hg/requires:lfs
268 $TESTTMP/client6_clone/.hg/requires:lfs
269 $TESTTMP/server/.hg/requires:lfs
269 $TESTTMP/server/.hg/requires:lfs
270
270
271 $ hg init $TESTTMP/client6_pull
271 $ hg init $TESTTMP/client6_pull
272 $ hg -R $TESTTMP/client6_pull pull -u -v http://localhost:$HGPORT
272 $ hg -R $TESTTMP/client6_pull pull -u -v http://localhost:$HGPORT
273 pulling from http://localhost:$HGPORT/
273 pulling from http://localhost:$HGPORT/
274 requesting all changes
274 requesting all changes
275 adding changesets
275 adding changesets
276 adding manifests
276 adding manifests
277 adding file changes
277 adding file changes
278 added 6 changesets with 5 changes to 5 files (+1 heads)
278 added 6 changesets with 5 changes to 5 files (+1 heads)
279 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
279 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
280 new changesets d437e1d24fbd:d3b84d50eacb
280 new changesets d437e1d24fbd:d3b84d50eacb
281 resolving manifests
281 resolving manifests
282 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
282 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
283 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
283 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
284 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
284 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
285 lfs: downloaded 1 files (25 bytes)
285 getting lfs2.txt
286 getting lfs2.txt
286 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
287 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
287 getting nonlfs2.txt
288 getting nonlfs2.txt
288 getting nonlfs3.txt
289 getting nonlfs3.txt
289 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 updated to "d3b84d50eacb: lfs file with lfs client"
291 updated to "d3b84d50eacb: lfs file with lfs client"
291 1 other heads for branch "default"
292 1 other heads for branch "default"
292 $ grep 'lfs' $TESTTMP/client6_pull/.hg/requires $SERVER_REQUIRES
293 $ grep 'lfs' $TESTTMP/client6_pull/.hg/requires $SERVER_REQUIRES
293 $TESTTMP/client6_pull/.hg/requires:lfs
294 $TESTTMP/client6_pull/.hg/requires:lfs
294 $TESTTMP/server/.hg/requires:lfs
295 $TESTTMP/server/.hg/requires:lfs
295
296
296 $ hg identify http://localhost:$HGPORT
297 $ hg identify http://localhost:$HGPORT
297 d3b84d50eacb
298 d3b84d50eacb
298
299
299 --------------------------------------------------------------------------------
300 --------------------------------------------------------------------------------
300 Misc: process dies early if a requirement exists and the extension is disabled
301 Misc: process dies early if a requirement exists and the extension is disabled
301
302
302 $ hg --config extensions.lfs=! summary
303 $ hg --config extensions.lfs=! summary
303 abort: repository requires features unknown to this Mercurial: lfs!
304 abort: repository requires features unknown to this Mercurial: lfs!
304 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
305 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
305 [255]
306 [255]
306
307
307 $ echo 'this is an lfs file' > $TESTTMP/client6_clone/lfspair1.bin
308 $ echo 'this is an lfs file' > $TESTTMP/client6_clone/lfspair1.bin
308 $ echo 'this is an lfs file too' > $TESTTMP/client6_clone/lfspair2.bin
309 $ echo 'this is an lfs file too' > $TESTTMP/client6_clone/lfspair2.bin
309 $ hg -R $TESTTMP/client6_clone ci -Aqm 'add lfs pair'
310 $ hg -R $TESTTMP/client6_clone ci -Aqm 'add lfs pair'
310 $ hg -R $TESTTMP/client6_clone push -q
311 $ hg -R $TESTTMP/client6_clone push -q
311
312
312 $ hg clone -qU http://localhost:$HGPORT $TESTTMP/bulkfetch
313 $ hg clone -qU http://localhost:$HGPORT $TESTTMP/bulkfetch
313
314
314 Export will prefetch all needed files across all needed revisions
315 Export will prefetch all needed files across all needed revisions
315
316
316 $ hg -R $TESTTMP/bulkfetch -v export -r 0:tip -o all.export
317 $ hg -R $TESTTMP/bulkfetch -v export -r 0:tip -o all.export
317 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
318 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
318 exporting patches:
319 exporting patches:
319 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
320 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
320 lfs: need to transfer 4 objects (92 bytes)
321 lfs: need to transfer 4 objects (92 bytes)
321 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
322 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
322 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
323 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
323 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
324 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
324 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
325 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
325 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
326 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
326 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
327 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
327 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
328 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
328 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
329 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
330 lfs: downloaded 4 files (92 bytes)
329 all.export
331 all.export
330 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
332 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
331 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
333 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
332 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
334 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
333 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
335 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
334
336
335 Export with selected files is used with `extdiff --patch`
337 Export with selected files is used with `extdiff --patch`
336
338
337 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
339 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
338 $ hg --config extensions.extdiff= \
340 $ hg --config extensions.extdiff= \
339 > -R $TESTTMP/bulkfetch -v extdiff -r 2:tip --patch $TESTTMP/bulkfetch/lfs.bin
341 > -R $TESTTMP/bulkfetch -v extdiff -r 2:tip --patch $TESTTMP/bulkfetch/lfs.bin
340 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
342 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
341 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
343 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
342 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
344 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
343 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
345 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
346 lfs: downloaded 1 files (23 bytes)
344 */hg-8374dc4052cb.patch (glob)
347 */hg-8374dc4052cb.patch (glob)
345 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
348 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
346 */hg-9640b57e77b1.patch (glob)
349 */hg-9640b57e77b1.patch (glob)
347 --- */hg-8374dc4052cb.patch * (glob)
350 --- */hg-8374dc4052cb.patch * (glob)
348 +++ */hg-9640b57e77b1.patch * (glob)
351 +++ */hg-9640b57e77b1.patch * (glob)
349 @@ -2,12 +2,7 @@
352 @@ -2,12 +2,7 @@
350 # User test
353 # User test
351 # Date 0 0
354 # Date 0 0
352 # Thu Jan 01 00:00:00 1970 +0000
355 # Thu Jan 01 00:00:00 1970 +0000
353 -# Node ID 8374dc4052cbd388e79d9dc4ddb29784097aa354
356 -# Node ID 8374dc4052cbd388e79d9dc4ddb29784097aa354
354 -# Parent 1477875038c60152e391238920a16381c627b487
357 -# Parent 1477875038c60152e391238920a16381c627b487
355 -lfs
358 -lfs
356 +# Node ID 9640b57e77b14c3a0144fb4478b6cc13e13ea0d1
359 +# Node ID 9640b57e77b14c3a0144fb4478b6cc13e13ea0d1
357 +# Parent d3b84d50eacbd56638e11abce6b8616aaba54420
360 +# Parent d3b84d50eacbd56638e11abce6b8616aaba54420
358 +add lfs pair
361 +add lfs pair
359
362
360 -diff -r 1477875038c6 -r 8374dc4052cb lfs.bin
363 -diff -r 1477875038c6 -r 8374dc4052cb lfs.bin
361 ---- /dev/null Thu Jan 01 00:00:00 1970 +0000
364 ---- /dev/null Thu Jan 01 00:00:00 1970 +0000
362 -+++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
365 -+++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
363 -@@ -0,0 +1,1 @@
366 -@@ -0,0 +1,1 @@
364 -+this is a big lfs file
367 -+this is a big lfs file
365 cleaning up temp directory
368 cleaning up temp directory
366 [1]
369 [1]
367
370
368 Diff will prefetch files
371 Diff will prefetch files
369
372
370 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
373 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
371 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip
374 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip
372 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
375 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
373 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
376 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
374 lfs: need to transfer 4 objects (92 bytes)
377 lfs: need to transfer 4 objects (92 bytes)
375 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
378 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
376 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
379 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
377 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
380 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
378 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
381 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
379 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
382 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
380 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
383 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
381 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
384 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
382 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
385 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
386 lfs: downloaded 4 files (92 bytes)
383 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
387 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
384 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
388 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
385 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
389 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
386 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
390 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
387 diff -r 8374dc4052cb -r 9640b57e77b1 lfs.bin
391 diff -r 8374dc4052cb -r 9640b57e77b1 lfs.bin
388 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
392 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
389 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
393 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
390 @@ -1,1 +0,0 @@
394 @@ -1,1 +0,0 @@
391 -this is a big lfs file
395 -this is a big lfs file
392 diff -r 8374dc4052cb -r 9640b57e77b1 lfs2.txt
396 diff -r 8374dc4052cb -r 9640b57e77b1 lfs2.txt
393 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
397 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
394 +++ b/lfs2.txt Thu Jan 01 00:00:00 1970 +0000
398 +++ b/lfs2.txt Thu Jan 01 00:00:00 1970 +0000
395 @@ -0,0 +1,1 @@
399 @@ -0,0 +1,1 @@
396 +this is another lfs file
400 +this is another lfs file
397 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair1.bin
401 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair1.bin
398 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
402 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
399 +++ b/lfspair1.bin Thu Jan 01 00:00:00 1970 +0000
403 +++ b/lfspair1.bin Thu Jan 01 00:00:00 1970 +0000
400 @@ -0,0 +1,1 @@
404 @@ -0,0 +1,1 @@
401 +this is an lfs file
405 +this is an lfs file
402 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
406 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
403 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
407 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
404 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
408 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
405 @@ -0,0 +1,1 @@
409 @@ -0,0 +1,1 @@
406 +this is an lfs file too
410 +this is an lfs file too
407 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs.txt
411 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs.txt
408 --- a/nonlfs.txt Thu Jan 01 00:00:00 1970 +0000
412 --- a/nonlfs.txt Thu Jan 01 00:00:00 1970 +0000
409 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
413 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
410 @@ -1,1 +0,0 @@
414 @@ -1,1 +0,0 @@
411 -non-lfs
415 -non-lfs
412 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs3.txt
416 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs3.txt
413 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
417 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
414 +++ b/nonlfs3.txt Thu Jan 01 00:00:00 1970 +0000
418 +++ b/nonlfs3.txt Thu Jan 01 00:00:00 1970 +0000
415 @@ -0,0 +1,1 @@
419 @@ -0,0 +1,1 @@
416 +non-lfs
420 +non-lfs
417
421
418 Only the files required by diff are prefetched
422 Only the files required by diff are prefetched
419
423
420 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
424 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
421 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip $TESTTMP/bulkfetch/lfspair2.bin
425 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip $TESTTMP/bulkfetch/lfspair2.bin
422 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
426 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
423 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
427 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
424 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
428 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
425 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
429 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
430 lfs: downloaded 1 files (24 bytes)
426 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
431 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
427 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
432 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
428 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
433 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
429 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
434 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
430 @@ -0,0 +1,1 @@
435 @@ -0,0 +1,1 @@
431 +this is an lfs file too
436 +this is an lfs file too
432
437
433 #endif
438 #endif
434
439
435 $ $PYTHON $TESTDIR/killdaemons.py $DAEMON_PIDS
440 $ $PYTHON $TESTDIR/killdaemons.py $DAEMON_PIDS
436
441
437 #if lfsremote-on
442 #if lfsremote-on
438 $ cat $TESTTMP/errors.log | grep '^[A-Z]'
443 $ cat $TESTTMP/errors.log | grep '^[A-Z]'
439 Traceback (most recent call last):
444 Traceback (most recent call last):
440 ValueError: no common changegroup version
445 ValueError: no common changegroup version
441 Traceback (most recent call last):
446 Traceback (most recent call last):
442 ValueError: no common changegroup version
447 ValueError: no common changegroup version
443 #else
448 #else
444 $ cat $TESTTMP/errors.log
449 $ cat $TESTTMP/errors.log
445 #endif
450 #endif
@@ -1,937 +1,942 b''
1 #require no-reposimplestore
1 #require no-reposimplestore
2 #testcases git-server hg-server
2 #testcases git-server hg-server
3
3
4 #if git-server
4 #if git-server
5 #require lfs-test-server
5 #require lfs-test-server
6 #else
6 #else
7 #require serve
7 #require serve
8 #endif
8 #endif
9
9
10 #if git-server
10 #if git-server
11 $ LFS_LISTEN="tcp://:$HGPORT"
11 $ LFS_LISTEN="tcp://:$HGPORT"
12 $ LFS_HOST="localhost:$HGPORT"
12 $ LFS_HOST="localhost:$HGPORT"
13 $ LFS_PUBLIC=1
13 $ LFS_PUBLIC=1
14 $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
14 $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
15 #else
15 #else
16 $ LFS_HOST="localhost:$HGPORT/.git/info/lfs"
16 $ LFS_HOST="localhost:$HGPORT/.git/info/lfs"
17 #endif
17 #endif
18
18
19 #if no-windows git-server
19 #if no-windows git-server
20 $ lfs-test-server &> lfs-server.log &
20 $ lfs-test-server &> lfs-server.log &
21 $ echo $! >> $DAEMON_PIDS
21 $ echo $! >> $DAEMON_PIDS
22 #endif
22 #endif
23
23
24 #if windows git-server
24 #if windows git-server
25 $ cat >> $TESTTMP/spawn.py <<EOF
25 $ cat >> $TESTTMP/spawn.py <<EOF
26 > import os
26 > import os
27 > import subprocess
27 > import subprocess
28 > import sys
28 > import sys
29 >
29 >
30 > for path in os.environ["PATH"].split(os.pathsep):
30 > for path in os.environ["PATH"].split(os.pathsep):
31 > exe = os.path.join(path, 'lfs-test-server.exe')
31 > exe = os.path.join(path, 'lfs-test-server.exe')
32 > if os.path.exists(exe):
32 > if os.path.exists(exe):
33 > with open('lfs-server.log', 'wb') as out:
33 > with open('lfs-server.log', 'wb') as out:
34 > p = subprocess.Popen(exe, stdout=out, stderr=out)
34 > p = subprocess.Popen(exe, stdout=out, stderr=out)
35 > sys.stdout.write('%s\n' % p.pid)
35 > sys.stdout.write('%s\n' % p.pid)
36 > sys.exit(0)
36 > sys.exit(0)
37 > sys.exit(1)
37 > sys.exit(1)
38 > EOF
38 > EOF
39 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
39 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
40 #endif
40 #endif
41
41
42 $ cat >> $HGRCPATH <<EOF
42 $ cat >> $HGRCPATH <<EOF
43 > [extensions]
43 > [extensions]
44 > lfs=
44 > lfs=
45 > [lfs]
45 > [lfs]
46 > url=http://foo:bar@$LFS_HOST
46 > url=http://foo:bar@$LFS_HOST
47 > track=all()
47 > track=all()
48 > [web]
48 > [web]
49 > push_ssl = False
49 > push_ssl = False
50 > allow-push = *
50 > allow-push = *
51 > EOF
51 > EOF
52
52
53 Use a separate usercache, otherwise the server sees what the client commits, and
53 Use a separate usercache, otherwise the server sees what the client commits, and
54 never requests a transfer.
54 never requests a transfer.
55
55
56 #if hg-server
56 #if hg-server
57 $ hg init server
57 $ hg init server
58 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
58 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
59 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
59 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
60 $ cat hg.pid >> $DAEMON_PIDS
60 $ cat hg.pid >> $DAEMON_PIDS
61 #endif
61 #endif
62
62
63 $ hg init repo1
63 $ hg init repo1
64 $ cd repo1
64 $ cd repo1
65 $ echo THIS-IS-LFS > a
65 $ echo THIS-IS-LFS > a
66 $ hg commit -m a -A a
66 $ hg commit -m a -A a
67
67
68 A push can be serviced directly from the usercache if it isn't in the local
68 A push can be serviced directly from the usercache if it isn't in the local
69 store.
69 store.
70
70
71 $ hg init ../repo2
71 $ hg init ../repo2
72 $ mv .hg/store/lfs .hg/store/lfs_
72 $ mv .hg/store/lfs .hg/store/lfs_
73 $ hg push ../repo2 --debug
73 $ hg push ../repo2 --debug
74 http auth: user foo, password ***
74 http auth: user foo, password ***
75 pushing to ../repo2
75 pushing to ../repo2
76 http auth: user foo, password ***
76 http auth: user foo, password ***
77 http auth: user foo, password ***
77 http auth: user foo, password ***
78 query 1; heads
78 query 1; heads
79 searching for changes
79 searching for changes
80 1 total queries in *s (glob)
80 1 total queries in *s (glob)
81 listing keys for "phases"
81 listing keys for "phases"
82 checking for updated bookmarks
82 checking for updated bookmarks
83 listing keys for "bookmarks"
83 listing keys for "bookmarks"
84 lfs: computing set of blobs to upload
84 lfs: computing set of blobs to upload
85 Status: 200
85 Status: 200
86 Content-Length: 309 (git-server !)
86 Content-Length: 309 (git-server !)
87 Content-Length: 350 (hg-server !)
87 Content-Length: 350 (hg-server !)
88 Content-Type: application/vnd.git-lfs+json
88 Content-Type: application/vnd.git-lfs+json
89 Date: $HTTP_DATE$
89 Date: $HTTP_DATE$
90 Server: testing stub value (hg-server !)
90 Server: testing stub value (hg-server !)
91 {
91 {
92 "objects": [
92 "objects": [
93 {
93 {
94 "actions": {
94 "actions": {
95 "upload": {
95 "upload": {
96 "expires_at": "$ISO_8601_DATE_TIME$"
96 "expires_at": "$ISO_8601_DATE_TIME$"
97 "header": {
97 "header": {
98 "Accept": "application/vnd.git-lfs"
98 "Accept": "application/vnd.git-lfs"
99 }
99 }
100 "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
100 "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
101 "href": "http://localhost:$HGPORT/.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (hg-server !)
101 "href": "http://localhost:$HGPORT/.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (hg-server !)
102 }
102 }
103 }
103 }
104 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
104 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
105 "size": 12
105 "size": 12
106 }
106 }
107 ]
107 ]
108 "transfer": "basic" (hg-server !)
108 "transfer": "basic" (hg-server !)
109 }
109 }
110 lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
110 lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
111 Status: 200 (git-server !)
111 Status: 200 (git-server !)
112 Status: 201 (hg-server !)
112 Status: 201 (hg-server !)
113 Content-Length: 0
113 Content-Length: 0
114 Content-Type: text/plain; charset=utf-8
114 Content-Type: text/plain; charset=utf-8
115 Date: $HTTP_DATE$
115 Date: $HTTP_DATE$
116 Server: testing stub value (hg-server !)
116 Server: testing stub value (hg-server !)
117 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
117 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
118 lfs: uploaded 1 files (12 bytes)
118 lfs: uploaded 1 files (12 bytes)
119 1 changesets found
119 1 changesets found
120 list of changesets:
120 list of changesets:
121 99a7098854a3984a5c9eab0fc7a2906697b7cb5c
121 99a7098854a3984a5c9eab0fc7a2906697b7cb5c
122 bundle2-output-bundle: "HG20", 4 parts total
122 bundle2-output-bundle: "HG20", 4 parts total
123 bundle2-output-part: "replycaps" * bytes payload (glob)
123 bundle2-output-part: "replycaps" * bytes payload (glob)
124 bundle2-output-part: "check:heads" streamed payload
124 bundle2-output-part: "check:heads" streamed payload
125 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
125 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
126 bundle2-output-part: "phase-heads" 24 bytes payload
126 bundle2-output-part: "phase-heads" 24 bytes payload
127 bundle2-input-bundle: with-transaction
127 bundle2-input-bundle: with-transaction
128 bundle2-input-part: "replycaps" supported
128 bundle2-input-part: "replycaps" supported
129 bundle2-input-part: total payload size * (glob)
129 bundle2-input-part: total payload size * (glob)
130 bundle2-input-part: "check:heads" supported
130 bundle2-input-part: "check:heads" supported
131 bundle2-input-part: total payload size 20
131 bundle2-input-part: total payload size 20
132 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
132 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
133 adding changesets
133 adding changesets
134 add changeset 99a7098854a3
134 add changeset 99a7098854a3
135 adding manifests
135 adding manifests
136 adding file changes
136 adding file changes
137 adding a revisions
137 adding a revisions
138 added 1 changesets with 1 changes to 1 files
138 added 1 changesets with 1 changes to 1 files
139 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
139 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
140 bundle2-input-part: total payload size 617
140 bundle2-input-part: total payload size 617
141 bundle2-input-part: "phase-heads" supported
141 bundle2-input-part: "phase-heads" supported
142 bundle2-input-part: total payload size 24
142 bundle2-input-part: total payload size 24
143 bundle2-input-bundle: 3 parts total
143 bundle2-input-bundle: 3 parts total
144 updating the branch cache
144 updating the branch cache
145 bundle2-output-bundle: "HG20", 1 parts total
145 bundle2-output-bundle: "HG20", 1 parts total
146 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
146 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
147 bundle2-input-bundle: no-transaction
147 bundle2-input-bundle: no-transaction
148 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
148 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
149 bundle2-input-bundle: 0 parts total
149 bundle2-input-bundle: 0 parts total
150 listing keys for "phases"
150 listing keys for "phases"
151 $ mv .hg/store/lfs_ .hg/store/lfs
151 $ mv .hg/store/lfs_ .hg/store/lfs
152
152
153 Clear the cache to force a download
153 Clear the cache to force a download
154 $ rm -rf `hg config lfs.usercache`
154 $ rm -rf `hg config lfs.usercache`
155 $ cd ../repo2
155 $ cd ../repo2
156 $ hg update tip --debug
156 $ hg update tip --debug
157 http auth: user foo, password ***
157 http auth: user foo, password ***
158 resolving manifests
158 resolving manifests
159 branchmerge: False, force: False, partial: False
159 branchmerge: False, force: False, partial: False
160 ancestor: 000000000000, local: 000000000000+, remote: 99a7098854a3
160 ancestor: 000000000000, local: 000000000000+, remote: 99a7098854a3
161 http auth: user foo, password ***
161 http auth: user foo, password ***
162 Status: 200
162 Status: 200
163 Content-Length: 311 (git-server !)
163 Content-Length: 311 (git-server !)
164 Content-Length: 352 (hg-server !)
164 Content-Length: 352 (hg-server !)
165 Content-Type: application/vnd.git-lfs+json
165 Content-Type: application/vnd.git-lfs+json
166 Date: $HTTP_DATE$
166 Date: $HTTP_DATE$
167 Server: testing stub value (hg-server !)
167 Server: testing stub value (hg-server !)
168 {
168 {
169 "objects": [
169 "objects": [
170 {
170 {
171 "actions": {
171 "actions": {
172 "download": {
172 "download": {
173 "expires_at": "$ISO_8601_DATE_TIME$"
173 "expires_at": "$ISO_8601_DATE_TIME$"
174 "header": {
174 "header": {
175 "Accept": "application/vnd.git-lfs"
175 "Accept": "application/vnd.git-lfs"
176 }
176 }
177 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
177 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
178 }
178 }
179 }
179 }
180 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
180 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
181 "size": 12
181 "size": 12
182 }
182 }
183 ]
183 ]
184 "transfer": "basic" (hg-server !)
184 "transfer": "basic" (hg-server !)
185 }
185 }
186 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
186 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
187 Status: 200
187 Status: 200
188 Content-Length: 12
188 Content-Length: 12
189 Content-Type: text/plain; charset=utf-8 (git-server !)
189 Content-Type: text/plain; charset=utf-8 (git-server !)
190 Content-Type: application/octet-stream (hg-server !)
190 Content-Type: application/octet-stream (hg-server !)
191 Date: $HTTP_DATE$
191 Date: $HTTP_DATE$
192 Server: testing stub value (hg-server !)
192 Server: testing stub value (hg-server !)
193 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
193 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
194 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
194 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
195 lfs: downloaded 1 files (12 bytes)
195 a: remote created -> g
196 a: remote created -> g
196 getting a
197 getting a
197 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
198 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
198 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
199
200
200 When the server has some blobs already. `hg serve` doesn't offer to upload
201 When the server has some blobs already. `hg serve` doesn't offer to upload
201 blobs that it already knows about. Note that lfs-test-server is simply
202 blobs that it already knows about. Note that lfs-test-server is simply
202 toggling the action to 'download'. The Batch API spec says it should omit the
203 toggling the action to 'download'. The Batch API spec says it should omit the
203 actions property completely.
204 actions property completely.
204
205
205 $ hg mv a b
206 $ hg mv a b
206 $ echo ANOTHER-LARGE-FILE > c
207 $ echo ANOTHER-LARGE-FILE > c
207 $ echo ANOTHER-LARGE-FILE2 > d
208 $ echo ANOTHER-LARGE-FILE2 > d
208 $ hg commit -m b-and-c -A b c d
209 $ hg commit -m b-and-c -A b c d
209 $ hg push ../repo1 --debug
210 $ hg push ../repo1 --debug
210 http auth: user foo, password ***
211 http auth: user foo, password ***
211 pushing to ../repo1
212 pushing to ../repo1
212 http auth: user foo, password ***
213 http auth: user foo, password ***
213 http auth: user foo, password ***
214 http auth: user foo, password ***
214 query 1; heads
215 query 1; heads
215 searching for changes
216 searching for changes
216 all remote heads known locally
217 all remote heads known locally
217 listing keys for "phases"
218 listing keys for "phases"
218 checking for updated bookmarks
219 checking for updated bookmarks
219 listing keys for "bookmarks"
220 listing keys for "bookmarks"
220 listing keys for "bookmarks"
221 listing keys for "bookmarks"
221 lfs: computing set of blobs to upload
222 lfs: computing set of blobs to upload
222 Status: 200
223 Status: 200
223 Content-Length: 901 (git-server !)
224 Content-Length: 901 (git-server !)
224 Content-Length: 755 (hg-server !)
225 Content-Length: 755 (hg-server !)
225 Content-Type: application/vnd.git-lfs+json
226 Content-Type: application/vnd.git-lfs+json
226 Date: $HTTP_DATE$
227 Date: $HTTP_DATE$
227 Server: testing stub value (hg-server !)
228 Server: testing stub value (hg-server !)
228 {
229 {
229 "objects": [
230 "objects": [
230 {
231 {
231 "actions": { (git-server !)
232 "actions": { (git-server !)
232 "download": { (git-server !)
233 "download": { (git-server !)
233 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
234 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
234 "header": { (git-server !)
235 "header": { (git-server !)
235 "Accept": "application/vnd.git-lfs" (git-server !)
236 "Accept": "application/vnd.git-lfs" (git-server !)
236 } (git-server !)
237 } (git-server !)
237 "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
238 "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
238 } (git-server !)
239 } (git-server !)
239 } (git-server !)
240 } (git-server !)
240 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
241 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
241 "size": 12
242 "size": 12
242 }
243 }
243 {
244 {
244 "actions": {
245 "actions": {
245 "upload": {
246 "upload": {
246 "expires_at": "$ISO_8601_DATE_TIME$"
247 "expires_at": "$ISO_8601_DATE_TIME$"
247 "header": {
248 "header": {
248 "Accept": "application/vnd.git-lfs"
249 "Accept": "application/vnd.git-lfs"
249 }
250 }
250 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
251 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
251 }
252 }
252 }
253 }
253 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
254 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
254 "size": 20
255 "size": 20
255 }
256 }
256 {
257 {
257 "actions": {
258 "actions": {
258 "upload": {
259 "upload": {
259 "expires_at": "$ISO_8601_DATE_TIME$"
260 "expires_at": "$ISO_8601_DATE_TIME$"
260 "header": {
261 "header": {
261 "Accept": "application/vnd.git-lfs"
262 "Accept": "application/vnd.git-lfs"
262 }
263 }
263 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
264 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
264 }
265 }
265 }
266 }
266 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
267 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
267 "size": 19
268 "size": 19
268 }
269 }
269 ]
270 ]
270 "transfer": "basic" (hg-server !)
271 "transfer": "basic" (hg-server !)
271 }
272 }
272 lfs: need to transfer 2 objects (39 bytes)
273 lfs: need to transfer 2 objects (39 bytes)
273 lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
274 lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
274 Status: 200 (git-server !)
275 Status: 200 (git-server !)
275 Status: 201 (hg-server !)
276 Status: 201 (hg-server !)
276 Content-Length: 0
277 Content-Length: 0
277 Content-Type: text/plain; charset=utf-8
278 Content-Type: text/plain; charset=utf-8
278 Date: $HTTP_DATE$
279 Date: $HTTP_DATE$
279 Server: testing stub value (hg-server !)
280 Server: testing stub value (hg-server !)
280 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
281 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
281 lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
282 lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
282 Status: 200 (git-server !)
283 Status: 200 (git-server !)
283 Status: 201 (hg-server !)
284 Status: 201 (hg-server !)
284 Content-Length: 0
285 Content-Length: 0
285 Content-Type: text/plain; charset=utf-8
286 Content-Type: text/plain; charset=utf-8
286 Date: $HTTP_DATE$
287 Date: $HTTP_DATE$
287 Server: testing stub value (hg-server !)
288 Server: testing stub value (hg-server !)
288 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
289 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
289 lfs: uploaded 2 files (39 bytes)
290 lfs: uploaded 2 files (39 bytes)
290 1 changesets found
291 1 changesets found
291 list of changesets:
292 list of changesets:
292 dfca2c9e2ef24996aa61ba2abd99277d884b3d63
293 dfca2c9e2ef24996aa61ba2abd99277d884b3d63
293 bundle2-output-bundle: "HG20", 5 parts total
294 bundle2-output-bundle: "HG20", 5 parts total
294 bundle2-output-part: "replycaps" * bytes payload (glob)
295 bundle2-output-part: "replycaps" * bytes payload (glob)
295 bundle2-output-part: "check:phases" 24 bytes payload
296 bundle2-output-part: "check:phases" 24 bytes payload
296 bundle2-output-part: "check:heads" streamed payload
297 bundle2-output-part: "check:heads" streamed payload
297 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
298 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
298 bundle2-output-part: "phase-heads" 24 bytes payload
299 bundle2-output-part: "phase-heads" 24 bytes payload
299 bundle2-input-bundle: with-transaction
300 bundle2-input-bundle: with-transaction
300 bundle2-input-part: "replycaps" supported
301 bundle2-input-part: "replycaps" supported
301 bundle2-input-part: total payload size * (glob)
302 bundle2-input-part: total payload size * (glob)
302 bundle2-input-part: "check:phases" supported
303 bundle2-input-part: "check:phases" supported
303 bundle2-input-part: total payload size 24
304 bundle2-input-part: total payload size 24
304 bundle2-input-part: "check:heads" supported
305 bundle2-input-part: "check:heads" supported
305 bundle2-input-part: total payload size 20
306 bundle2-input-part: total payload size 20
306 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
307 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
307 adding changesets
308 adding changesets
308 add changeset dfca2c9e2ef2
309 add changeset dfca2c9e2ef2
309 adding manifests
310 adding manifests
310 adding file changes
311 adding file changes
311 adding b revisions
312 adding b revisions
312 adding c revisions
313 adding c revisions
313 adding d revisions
314 adding d revisions
314 added 1 changesets with 3 changes to 3 files
315 added 1 changesets with 3 changes to 3 files
315 bundle2-input-part: total payload size 1315
316 bundle2-input-part: total payload size 1315
316 bundle2-input-part: "phase-heads" supported
317 bundle2-input-part: "phase-heads" supported
317 bundle2-input-part: total payload size 24
318 bundle2-input-part: total payload size 24
318 bundle2-input-bundle: 4 parts total
319 bundle2-input-bundle: 4 parts total
319 updating the branch cache
320 updating the branch cache
320 bundle2-output-bundle: "HG20", 1 parts total
321 bundle2-output-bundle: "HG20", 1 parts total
321 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
322 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
322 bundle2-input-bundle: no-transaction
323 bundle2-input-bundle: no-transaction
323 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
324 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
324 bundle2-input-bundle: 0 parts total
325 bundle2-input-bundle: 0 parts total
325 listing keys for "phases"
326 listing keys for "phases"
326
327
327 Clear the cache to force a download
328 Clear the cache to force a download
328 $ rm -rf `hg config lfs.usercache`
329 $ rm -rf `hg config lfs.usercache`
329 $ hg --repo ../repo1 update tip --debug
330 $ hg --repo ../repo1 update tip --debug
330 http auth: user foo, password ***
331 http auth: user foo, password ***
331 resolving manifests
332 resolving manifests
332 branchmerge: False, force: False, partial: False
333 branchmerge: False, force: False, partial: False
333 ancestor: 99a7098854a3, local: 99a7098854a3+, remote: dfca2c9e2ef2
334 ancestor: 99a7098854a3, local: 99a7098854a3+, remote: dfca2c9e2ef2
334 http auth: user foo, password ***
335 http auth: user foo, password ***
335 Status: 200
336 Status: 200
336 Content-Length: 608 (git-server !)
337 Content-Length: 608 (git-server !)
337 Content-Length: 670 (hg-server !)
338 Content-Length: 670 (hg-server !)
338 Content-Type: application/vnd.git-lfs+json
339 Content-Type: application/vnd.git-lfs+json
339 Date: $HTTP_DATE$
340 Date: $HTTP_DATE$
340 Server: testing stub value (hg-server !)
341 Server: testing stub value (hg-server !)
341 {
342 {
342 "objects": [
343 "objects": [
343 {
344 {
344 "actions": {
345 "actions": {
345 "download": {
346 "download": {
346 "expires_at": "$ISO_8601_DATE_TIME$"
347 "expires_at": "$ISO_8601_DATE_TIME$"
347 "header": {
348 "header": {
348 "Accept": "application/vnd.git-lfs"
349 "Accept": "application/vnd.git-lfs"
349 }
350 }
350 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
351 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
351 }
352 }
352 }
353 }
353 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
354 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
354 "size": 20
355 "size": 20
355 }
356 }
356 {
357 {
357 "actions": {
358 "actions": {
358 "download": {
359 "download": {
359 "expires_at": "$ISO_8601_DATE_TIME$"
360 "expires_at": "$ISO_8601_DATE_TIME$"
360 "header": {
361 "header": {
361 "Accept": "application/vnd.git-lfs"
362 "Accept": "application/vnd.git-lfs"
362 }
363 }
363 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
364 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
364 }
365 }
365 }
366 }
366 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
367 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
367 "size": 19
368 "size": 19
368 }
369 }
369 ]
370 ]
370 "transfer": "basic" (hg-server !)
371 "transfer": "basic" (hg-server !)
371 }
372 }
372 lfs: need to transfer 2 objects (39 bytes)
373 lfs: need to transfer 2 objects (39 bytes)
373 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
374 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
374 Status: 200
375 Status: 200
375 Content-Length: 20
376 Content-Length: 20
376 Content-Type: text/plain; charset=utf-8 (git-server !)
377 Content-Type: text/plain; charset=utf-8 (git-server !)
377 Content-Type: application/octet-stream (hg-server !)
378 Content-Type: application/octet-stream (hg-server !)
378 Date: $HTTP_DATE$
379 Date: $HTTP_DATE$
379 Server: testing stub value (hg-server !)
380 Server: testing stub value (hg-server !)
380 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
381 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
381 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
382 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
382 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
383 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
383 Status: 200
384 Status: 200
384 Content-Length: 19
385 Content-Length: 19
385 Content-Type: text/plain; charset=utf-8 (git-server !)
386 Content-Type: text/plain; charset=utf-8 (git-server !)
386 Content-Type: application/octet-stream (hg-server !)
387 Content-Type: application/octet-stream (hg-server !)
387 Date: $HTTP_DATE$
388 Date: $HTTP_DATE$
388 Server: testing stub value (hg-server !)
389 Server: testing stub value (hg-server !)
389 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
390 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
390 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
391 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
392 lfs: downloaded 2 files (39 bytes)
391 b: remote created -> g
393 b: remote created -> g
392 getting b
394 getting b
393 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
395 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
394 c: remote created -> g
396 c: remote created -> g
395 getting c
397 getting c
396 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
398 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
397 d: remote created -> g
399 d: remote created -> g
398 getting d
400 getting d
399 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
401 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
400 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
401
403
402 Test a corrupt file download, but clear the cache first to force a download.
404 Test a corrupt file download, but clear the cache first to force a download.
403 `hg serve` indicates a corrupt file without transferring it, unlike
405 `hg serve` indicates a corrupt file without transferring it, unlike
404 lfs-test-server.
406 lfs-test-server.
405
407
406 $ rm -rf `hg config lfs.usercache`
408 $ rm -rf `hg config lfs.usercache`
407 #if git-server
409 #if git-server
408 $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
410 $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
409 $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
411 $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
410 #else
412 #else
411 $ cp $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
413 $ cp $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
412 $ echo 'damage' > $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
414 $ echo 'damage' > $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
413 #endif
415 #endif
414 $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
416 $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
415 $ rm ../repo1/*
417 $ rm ../repo1/*
416
418
417 TODO: give the proper error indication from `hg serve`
419 TODO: give the proper error indication from `hg serve`
418
420
419 $ hg --repo ../repo1 update -C tip --debug
421 $ hg --repo ../repo1 update -C tip --debug
420 http auth: user foo, password ***
422 http auth: user foo, password ***
421 resolving manifests
423 resolving manifests
422 branchmerge: False, force: True, partial: False
424 branchmerge: False, force: True, partial: False
423 ancestor: dfca2c9e2ef2+, local: dfca2c9e2ef2+, remote: dfca2c9e2ef2
425 ancestor: dfca2c9e2ef2+, local: dfca2c9e2ef2+, remote: dfca2c9e2ef2
424 http auth: user foo, password ***
426 http auth: user foo, password ***
425 Status: 200
427 Status: 200
426 Content-Length: 311 (git-server !)
428 Content-Length: 311 (git-server !)
427 Content-Length: 183 (hg-server !)
429 Content-Length: 183 (hg-server !)
428 Content-Type: application/vnd.git-lfs+json
430 Content-Type: application/vnd.git-lfs+json
429 Date: $HTTP_DATE$
431 Date: $HTTP_DATE$
430 Server: testing stub value (hg-server !)
432 Server: testing stub value (hg-server !)
431 {
433 {
432 "objects": [
434 "objects": [
433 {
435 {
434 "actions": { (git-server !)
436 "actions": { (git-server !)
435 "download": { (git-server !)
437 "download": { (git-server !)
436 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
438 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
437 "header": { (git-server !)
439 "header": { (git-server !)
438 "Accept": "application/vnd.git-lfs" (git-server !)
440 "Accept": "application/vnd.git-lfs" (git-server !)
439 } (git-server !)
441 } (git-server !)
440 "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (git-server !)
442 "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (git-server !)
441 } (git-server !)
443 } (git-server !)
442 "error": { (hg-server !)
444 "error": { (hg-server !)
443 "code": 422 (hg-server !)
445 "code": 422 (hg-server !)
444 "message": "The object is corrupt" (hg-server !)
446 "message": "The object is corrupt" (hg-server !)
445 }
447 }
446 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
448 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
447 "size": 19
449 "size": 19
448 }
450 }
449 ]
451 ]
450 "transfer": "basic" (hg-server !)
452 "transfer": "basic" (hg-server !)
451 }
453 }
452 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes) (git-server !)
454 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes) (git-server !)
453 Status: 200 (git-server !)
455 Status: 200 (git-server !)
454 Content-Length: 7 (git-server !)
456 Content-Length: 7 (git-server !)
455 Content-Type: text/plain; charset=utf-8 (git-server !)
457 Content-Type: text/plain; charset=utf-8 (git-server !)
456 Date: $HTTP_DATE$ (git-server !)
458 Date: $HTTP_DATE$ (git-server !)
457 abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (git-server !)
459 abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (git-server !)
458 abort: LFS server error for "c": Validation error! (hg-server !)
460 abort: LFS server error for "c": Validation error! (hg-server !)
459 [255]
461 [255]
460
462
461 The corrupted blob is not added to the usercache or local store
463 The corrupted blob is not added to the usercache or local store
462
464
463 $ test -f ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
465 $ test -f ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
464 [1]
466 [1]
465 $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
467 $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
466 [1]
468 [1]
467 #if git-server
469 #if git-server
468 $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
470 $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
469 #else
471 #else
470 $ cp blob $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
472 $ cp blob $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
471 #endif
473 #endif
472
474
473 Test a corrupted file upload
475 Test a corrupted file upload
474
476
475 $ echo 'another lfs blob' > b
477 $ echo 'another lfs blob' > b
476 $ hg ci -m 'another blob'
478 $ hg ci -m 'another blob'
477 $ echo 'damage' > .hg/store/lfs/objects/e6/59058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
479 $ echo 'damage' > .hg/store/lfs/objects/e6/59058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
478 $ hg push --debug ../repo1
480 $ hg push --debug ../repo1
479 http auth: user foo, password ***
481 http auth: user foo, password ***
480 pushing to ../repo1
482 pushing to ../repo1
481 http auth: user foo, password ***
483 http auth: user foo, password ***
482 http auth: user foo, password ***
484 http auth: user foo, password ***
483 query 1; heads
485 query 1; heads
484 searching for changes
486 searching for changes
485 all remote heads known locally
487 all remote heads known locally
486 listing keys for "phases"
488 listing keys for "phases"
487 checking for updated bookmarks
489 checking for updated bookmarks
488 listing keys for "bookmarks"
490 listing keys for "bookmarks"
489 listing keys for "bookmarks"
491 listing keys for "bookmarks"
490 lfs: computing set of blobs to upload
492 lfs: computing set of blobs to upload
491 Status: 200
493 Status: 200
492 Content-Length: 309 (git-server !)
494 Content-Length: 309 (git-server !)
493 Content-Length: 350 (hg-server !)
495 Content-Length: 350 (hg-server !)
494 Content-Type: application/vnd.git-lfs+json
496 Content-Type: application/vnd.git-lfs+json
495 Date: $HTTP_DATE$
497 Date: $HTTP_DATE$
496 Server: testing stub value (hg-server !)
498 Server: testing stub value (hg-server !)
497 {
499 {
498 "objects": [
500 "objects": [
499 {
501 {
500 "actions": {
502 "actions": {
501 "upload": {
503 "upload": {
502 "expires_at": "$ISO_8601_DATE_TIME$"
504 "expires_at": "$ISO_8601_DATE_TIME$"
503 "header": {
505 "header": {
504 "Accept": "application/vnd.git-lfs"
506 "Accept": "application/vnd.git-lfs"
505 }
507 }
506 "href": "http://localhost:$HGPORT/*/e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0" (glob)
508 "href": "http://localhost:$HGPORT/*/e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0" (glob)
507 }
509 }
508 }
510 }
509 "oid": "e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0"
511 "oid": "e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0"
510 "size": 17
512 "size": 17
511 }
513 }
512 ]
514 ]
513 "transfer": "basic" (hg-server !)
515 "transfer": "basic" (hg-server !)
514 }
516 }
515 lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
517 lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
516 abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
518 abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
517 (run hg verify)
519 (run hg verify)
518 [255]
520 [255]
519
521
520 Archive will prefetch blobs in a group
522 Archive will prefetch blobs in a group
521
523
522 $ rm -rf .hg/store/lfs `hg config lfs.usercache`
524 $ rm -rf .hg/store/lfs `hg config lfs.usercache`
523 $ hg archive --debug -r 1 ../archive
525 $ hg archive --debug -r 1 ../archive
524 http auth: user foo, password ***
526 http auth: user foo, password ***
525 http auth: user foo, password ***
527 http auth: user foo, password ***
526 Status: 200
528 Status: 200
527 Content-Length: 905 (git-server !)
529 Content-Length: 905 (git-server !)
528 Content-Length: 988 (hg-server !)
530 Content-Length: 988 (hg-server !)
529 Content-Type: application/vnd.git-lfs+json
531 Content-Type: application/vnd.git-lfs+json
530 Date: $HTTP_DATE$
532 Date: $HTTP_DATE$
531 Server: testing stub value (hg-server !)
533 Server: testing stub value (hg-server !)
532 {
534 {
533 "objects": [
535 "objects": [
534 {
536 {
535 "actions": {
537 "actions": {
536 "download": {
538 "download": {
537 "expires_at": "$ISO_8601_DATE_TIME$"
539 "expires_at": "$ISO_8601_DATE_TIME$"
538 "header": {
540 "header": {
539 "Accept": "application/vnd.git-lfs"
541 "Accept": "application/vnd.git-lfs"
540 }
542 }
541 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
543 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
542 }
544 }
543 }
545 }
544 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
546 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
545 "size": 12
547 "size": 12
546 }
548 }
547 {
549 {
548 "actions": {
550 "actions": {
549 "download": {
551 "download": {
550 "expires_at": "$ISO_8601_DATE_TIME$"
552 "expires_at": "$ISO_8601_DATE_TIME$"
551 "header": {
553 "header": {
552 "Accept": "application/vnd.git-lfs"
554 "Accept": "application/vnd.git-lfs"
553 }
555 }
554 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
556 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
555 }
557 }
556 }
558 }
557 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
559 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
558 "size": 20
560 "size": 20
559 }
561 }
560 {
562 {
561 "actions": {
563 "actions": {
562 "download": {
564 "download": {
563 "expires_at": "$ISO_8601_DATE_TIME$"
565 "expires_at": "$ISO_8601_DATE_TIME$"
564 "header": {
566 "header": {
565 "Accept": "application/vnd.git-lfs"
567 "Accept": "application/vnd.git-lfs"
566 }
568 }
567 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
569 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
568 }
570 }
569 }
571 }
570 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
572 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
571 "size": 19
573 "size": 19
572 }
574 }
573 ]
575 ]
574 "transfer": "basic" (hg-server !)
576 "transfer": "basic" (hg-server !)
575 }
577 }
576 lfs: need to transfer 3 objects (51 bytes)
578 lfs: need to transfer 3 objects (51 bytes)
577 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
579 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
578 Status: 200
580 Status: 200
579 Content-Length: 12
581 Content-Length: 12
580 Content-Type: text/plain; charset=utf-8 (git-server !)
582 Content-Type: text/plain; charset=utf-8 (git-server !)
581 Content-Type: application/octet-stream (hg-server !)
583 Content-Type: application/octet-stream (hg-server !)
582 Date: $HTTP_DATE$
584 Date: $HTTP_DATE$
583 Server: testing stub value (hg-server !)
585 Server: testing stub value (hg-server !)
584 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
586 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
585 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
587 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
586 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
588 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
587 Status: 200
589 Status: 200
588 Content-Length: 20
590 Content-Length: 20
589 Content-Type: text/plain; charset=utf-8 (git-server !)
591 Content-Type: text/plain; charset=utf-8 (git-server !)
590 Content-Type: application/octet-stream (hg-server !)
592 Content-Type: application/octet-stream (hg-server !)
591 Date: $HTTP_DATE$
593 Date: $HTTP_DATE$
592 Server: testing stub value (hg-server !)
594 Server: testing stub value (hg-server !)
593 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
595 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
594 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
596 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
595 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
597 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
596 Status: 200
598 Status: 200
597 Content-Length: 19
599 Content-Length: 19
598 Content-Type: text/plain; charset=utf-8 (git-server !)
600 Content-Type: text/plain; charset=utf-8 (git-server !)
599 Content-Type: application/octet-stream (hg-server !)
601 Content-Type: application/octet-stream (hg-server !)
600 Date: $HTTP_DATE$
602 Date: $HTTP_DATE$
601 Server: testing stub value (hg-server !)
603 Server: testing stub value (hg-server !)
602 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
604 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
603 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
605 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
606 lfs: downloaded 3 files (51 bytes)
604 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
607 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
605 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
608 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
606 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
609 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
607 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
610 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
608 $ find ../archive | sort
611 $ find ../archive | sort
609 ../archive
612 ../archive
610 ../archive/.hg_archival.txt
613 ../archive/.hg_archival.txt
611 ../archive/a
614 ../archive/a
612 ../archive/b
615 ../archive/b
613 ../archive/c
616 ../archive/c
614 ../archive/d
617 ../archive/d
615
618
616 Cat will prefetch blobs in a group
619 Cat will prefetch blobs in a group
617
620
618 $ rm -rf .hg/store/lfs `hg config lfs.usercache`
621 $ rm -rf .hg/store/lfs `hg config lfs.usercache`
619 $ hg cat --debug -r 1 a b c nonexistent
622 $ hg cat --debug -r 1 a b c nonexistent
620 http auth: user foo, password ***
623 http auth: user foo, password ***
621 http auth: user foo, password ***
624 http auth: user foo, password ***
622 Status: 200
625 Status: 200
623 Content-Length: 608 (git-server !)
626 Content-Length: 608 (git-server !)
624 Content-Length: 670 (hg-server !)
627 Content-Length: 670 (hg-server !)
625 Content-Type: application/vnd.git-lfs+json
628 Content-Type: application/vnd.git-lfs+json
626 Date: $HTTP_DATE$
629 Date: $HTTP_DATE$
627 Server: testing stub value (hg-server !)
630 Server: testing stub value (hg-server !)
628 {
631 {
629 "objects": [
632 "objects": [
630 {
633 {
631 "actions": {
634 "actions": {
632 "download": {
635 "download": {
633 "expires_at": "$ISO_8601_DATE_TIME$"
636 "expires_at": "$ISO_8601_DATE_TIME$"
634 "header": {
637 "header": {
635 "Accept": "application/vnd.git-lfs"
638 "Accept": "application/vnd.git-lfs"
636 }
639 }
637 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
640 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
638 }
641 }
639 }
642 }
640 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
643 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
641 "size": 12
644 "size": 12
642 }
645 }
643 {
646 {
644 "actions": {
647 "actions": {
645 "download": {
648 "download": {
646 "expires_at": "$ISO_8601_DATE_TIME$"
649 "expires_at": "$ISO_8601_DATE_TIME$"
647 "header": {
650 "header": {
648 "Accept": "application/vnd.git-lfs"
651 "Accept": "application/vnd.git-lfs"
649 }
652 }
650 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
653 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
651 }
654 }
652 }
655 }
653 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
656 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
654 "size": 19
657 "size": 19
655 }
658 }
656 ]
659 ]
657 "transfer": "basic" (hg-server !)
660 "transfer": "basic" (hg-server !)
658 }
661 }
659 lfs: need to transfer 2 objects (31 bytes)
662 lfs: need to transfer 2 objects (31 bytes)
660 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
663 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
661 Status: 200
664 Status: 200
662 Content-Length: 12
665 Content-Length: 12
663 Content-Type: text/plain; charset=utf-8 (git-server !)
666 Content-Type: text/plain; charset=utf-8 (git-server !)
664 Content-Type: application/octet-stream (hg-server !)
667 Content-Type: application/octet-stream (hg-server !)
665 Date: $HTTP_DATE$
668 Date: $HTTP_DATE$
666 Server: testing stub value (hg-server !)
669 Server: testing stub value (hg-server !)
667 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
670 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
668 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
671 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
669 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
672 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
670 Status: 200
673 Status: 200
671 Content-Length: 19
674 Content-Length: 19
672 Content-Type: text/plain; charset=utf-8 (git-server !)
675 Content-Type: text/plain; charset=utf-8 (git-server !)
673 Content-Type: application/octet-stream (hg-server !)
676 Content-Type: application/octet-stream (hg-server !)
674 Date: $HTTP_DATE$
677 Date: $HTTP_DATE$
675 Server: testing stub value (hg-server !)
678 Server: testing stub value (hg-server !)
676 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
679 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
677 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
680 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
681 lfs: downloaded 2 files (31 bytes)
678 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
682 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
679 THIS-IS-LFS
683 THIS-IS-LFS
680 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
684 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
681 THIS-IS-LFS
685 THIS-IS-LFS
682 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
686 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
683 ANOTHER-LARGE-FILE
687 ANOTHER-LARGE-FILE
684 nonexistent: no such file in rev dfca2c9e2ef2
688 nonexistent: no such file in rev dfca2c9e2ef2
685
689
686 Revert will prefetch blobs in a group
690 Revert will prefetch blobs in a group
687
691
688 $ rm -rf .hg/store/lfs
692 $ rm -rf .hg/store/lfs
689 $ rm -rf `hg config lfs.usercache`
693 $ rm -rf `hg config lfs.usercache`
690 $ rm *
694 $ rm *
691 $ hg revert --all -r 1 --debug
695 $ hg revert --all -r 1 --debug
692 http auth: user foo, password ***
696 http auth: user foo, password ***
693 adding a
697 adding a
694 reverting b
698 reverting b
695 reverting c
699 reverting c
696 reverting d
700 reverting d
697 http auth: user foo, password ***
701 http auth: user foo, password ***
698 Status: 200
702 Status: 200
699 Content-Length: 905 (git-server !)
703 Content-Length: 905 (git-server !)
700 Content-Length: 988 (hg-server !)
704 Content-Length: 988 (hg-server !)
701 Content-Type: application/vnd.git-lfs+json
705 Content-Type: application/vnd.git-lfs+json
702 Date: $HTTP_DATE$
706 Date: $HTTP_DATE$
703 Server: testing stub value (hg-server !)
707 Server: testing stub value (hg-server !)
704 {
708 {
705 "objects": [
709 "objects": [
706 {
710 {
707 "actions": {
711 "actions": {
708 "download": {
712 "download": {
709 "expires_at": "$ISO_8601_DATE_TIME$"
713 "expires_at": "$ISO_8601_DATE_TIME$"
710 "header": {
714 "header": {
711 "Accept": "application/vnd.git-lfs"
715 "Accept": "application/vnd.git-lfs"
712 }
716 }
713 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
717 "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
714 }
718 }
715 }
719 }
716 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
720 "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
717 "size": 12
721 "size": 12
718 }
722 }
719 {
723 {
720 "actions": {
724 "actions": {
721 "download": {
725 "download": {
722 "expires_at": "$ISO_8601_DATE_TIME$"
726 "expires_at": "$ISO_8601_DATE_TIME$"
723 "header": {
727 "header": {
724 "Accept": "application/vnd.git-lfs"
728 "Accept": "application/vnd.git-lfs"
725 }
729 }
726 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
730 "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
727 }
731 }
728 }
732 }
729 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
733 "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
730 "size": 20
734 "size": 20
731 }
735 }
732 {
736 {
733 "actions": {
737 "actions": {
734 "download": {
738 "download": {
735 "expires_at": "$ISO_8601_DATE_TIME$"
739 "expires_at": "$ISO_8601_DATE_TIME$"
736 "header": {
740 "header": {
737 "Accept": "application/vnd.git-lfs"
741 "Accept": "application/vnd.git-lfs"
738 }
742 }
739 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
743 "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
740 }
744 }
741 }
745 }
742 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
746 "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
743 "size": 19
747 "size": 19
744 }
748 }
745 ]
749 ]
746 "transfer": "basic" (hg-server !)
750 "transfer": "basic" (hg-server !)
747 }
751 }
748 lfs: need to transfer 3 objects (51 bytes)
752 lfs: need to transfer 3 objects (51 bytes)
749 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
753 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
750 Status: 200
754 Status: 200
751 Content-Length: 12
755 Content-Length: 12
752 Content-Type: text/plain; charset=utf-8 (git-server !)
756 Content-Type: text/plain; charset=utf-8 (git-server !)
753 Content-Type: application/octet-stream (hg-server !)
757 Content-Type: application/octet-stream (hg-server !)
754 Date: $HTTP_DATE$
758 Date: $HTTP_DATE$
755 Server: testing stub value (hg-server !)
759 Server: testing stub value (hg-server !)
756 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
760 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
757 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
761 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
758 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
762 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
759 Status: 200
763 Status: 200
760 Content-Length: 20
764 Content-Length: 20
761 Content-Type: text/plain; charset=utf-8 (git-server !)
765 Content-Type: text/plain; charset=utf-8 (git-server !)
762 Content-Type: application/octet-stream (hg-server !)
766 Content-Type: application/octet-stream (hg-server !)
763 Date: $HTTP_DATE$
767 Date: $HTTP_DATE$
764 Server: testing stub value (hg-server !)
768 Server: testing stub value (hg-server !)
765 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
769 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
766 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
770 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
767 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
771 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
768 Status: 200
772 Status: 200
769 Content-Length: 19
773 Content-Length: 19
770 Content-Type: text/plain; charset=utf-8 (git-server !)
774 Content-Type: text/plain; charset=utf-8 (git-server !)
771 Content-Type: application/octet-stream (hg-server !)
775 Content-Type: application/octet-stream (hg-server !)
772 Date: $HTTP_DATE$
776 Date: $HTTP_DATE$
773 Server: testing stub value (hg-server !)
777 Server: testing stub value (hg-server !)
774 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
778 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
775 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
779 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
780 lfs: downloaded 3 files (51 bytes)
776 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
781 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
777 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
782 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
778 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
783 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
779 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
784 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
780
785
781 Check error message when the remote missed a blob:
786 Check error message when the remote missed a blob:
782
787
783 $ echo FFFFF > b
788 $ echo FFFFF > b
784 $ hg commit -m b -A b
789 $ hg commit -m b -A b
785 $ echo FFFFF >> b
790 $ echo FFFFF >> b
786 $ hg commit -m b b
791 $ hg commit -m b b
787 $ rm -rf .hg/store/lfs
792 $ rm -rf .hg/store/lfs
788 $ rm -rf `hg config lfs.usercache`
793 $ rm -rf `hg config lfs.usercache`
789 $ hg update -C '.^' --debug
794 $ hg update -C '.^' --debug
790 http auth: user foo, password ***
795 http auth: user foo, password ***
791 resolving manifests
796 resolving manifests
792 branchmerge: False, force: True, partial: False
797 branchmerge: False, force: True, partial: False
793 ancestor: 62fdbaf221c6+, local: 62fdbaf221c6+, remote: ef0564edf47e
798 ancestor: 62fdbaf221c6+, local: 62fdbaf221c6+, remote: ef0564edf47e
794 http auth: user foo, password ***
799 http auth: user foo, password ***
795 Status: 200
800 Status: 200
796 Content-Length: 308 (git-server !)
801 Content-Length: 308 (git-server !)
797 Content-Length: 186 (hg-server !)
802 Content-Length: 186 (hg-server !)
798 Content-Type: application/vnd.git-lfs+json
803 Content-Type: application/vnd.git-lfs+json
799 Date: $HTTP_DATE$
804 Date: $HTTP_DATE$
800 Server: testing stub value (hg-server !)
805 Server: testing stub value (hg-server !)
801 {
806 {
802 "objects": [
807 "objects": [
803 {
808 {
804 "actions": { (git-server !)
809 "actions": { (git-server !)
805 "upload": { (git-server !)
810 "upload": { (git-server !)
806 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
811 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
807 "header": { (git-server !)
812 "header": { (git-server !)
808 "Accept": "application/vnd.git-lfs" (git-server !)
813 "Accept": "application/vnd.git-lfs" (git-server !)
809 } (git-server !)
814 } (git-server !)
810 "href": "http://localhost:$HGPORT/objects/8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13" (git-server !)
815 "href": "http://localhost:$HGPORT/objects/8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13" (git-server !)
811 } (git-server !)
816 } (git-server !)
812 "error": { (hg-server !)
817 "error": { (hg-server !)
813 "code": 404 (hg-server !)
818 "code": 404 (hg-server !)
814 "message": "The object does not exist" (hg-server !)
819 "message": "The object does not exist" (hg-server !)
815 }
820 }
816 "oid": "8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13"
821 "oid": "8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13"
817 "size": 6
822 "size": 6
818 }
823 }
819 ]
824 ]
820 "transfer": "basic" (hg-server !)
825 "transfer": "basic" (hg-server !)
821 }
826 }
822 abort: LFS server error for "b": The object does not exist!
827 abort: LFS server error for "b": The object does not exist!
823 [255]
828 [255]
824
829
825 Check error message when object does not exist:
830 Check error message when object does not exist:
826
831
827 $ cd $TESTTMP
832 $ cd $TESTTMP
828 $ hg init test && cd test
833 $ hg init test && cd test
829 $ echo "[extensions]" >> .hg/hgrc
834 $ echo "[extensions]" >> .hg/hgrc
830 $ echo "lfs=" >> .hg/hgrc
835 $ echo "lfs=" >> .hg/hgrc
831 $ echo "[lfs]" >> .hg/hgrc
836 $ echo "[lfs]" >> .hg/hgrc
832 $ echo "threshold=1" >> .hg/hgrc
837 $ echo "threshold=1" >> .hg/hgrc
833 $ echo a > a
838 $ echo a > a
834 $ hg add a
839 $ hg add a
835 $ hg commit -m 'test'
840 $ hg commit -m 'test'
836 $ echo aaaaa > a
841 $ echo aaaaa > a
837 $ hg commit -m 'largefile'
842 $ hg commit -m 'largefile'
838 $ hg debugdata a 1 # verify this is no the file content but includes "oid", the LFS "pointer".
843 $ hg debugdata a 1 # verify this is no the file content but includes "oid", the LFS "pointer".
839 version https://git-lfs.github.com/spec/v1
844 version https://git-lfs.github.com/spec/v1
840 oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
845 oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
841 size 6
846 size 6
842 x-is-binary 0
847 x-is-binary 0
843 $ cd ..
848 $ cd ..
844 $ rm -rf `hg config lfs.usercache`
849 $ rm -rf `hg config lfs.usercache`
845
850
846 (Restart the server in a different location so it no longer has the content)
851 (Restart the server in a different location so it no longer has the content)
847
852
848 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
853 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
849
854
850 #if hg-server
855 #if hg-server
851 $ cat $TESTTMP/access.log $TESTTMP/errors.log
856 $ cat $TESTTMP/access.log $TESTTMP/errors.log
852 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
857 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
853 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 201 - (glob)
858 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 201 - (glob)
854 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
859 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
855 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
860 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
856 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
861 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
857 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 201 - (glob)
862 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 201 - (glob)
858 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 201 - (glob)
863 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 201 - (glob)
859 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
864 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
860 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
865 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
861 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
866 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
862 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
867 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
863 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
868 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
864 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
869 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
865 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
870 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
866 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
871 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
867 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
872 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
868 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
873 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
869 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
874 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
870 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
875 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
871 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
876 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
872 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
877 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
873 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
878 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
874 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
879 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
875 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
880 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
876 #endif
881 #endif
877
882
878 $ rm $DAEMON_PIDS
883 $ rm $DAEMON_PIDS
879 $ mkdir $TESTTMP/lfs-server2
884 $ mkdir $TESTTMP/lfs-server2
880 $ cd $TESTTMP/lfs-server2
885 $ cd $TESTTMP/lfs-server2
881 #if no-windows git-server
886 #if no-windows git-server
882 $ lfs-test-server &> lfs-server.log &
887 $ lfs-test-server &> lfs-server.log &
883 $ echo $! >> $DAEMON_PIDS
888 $ echo $! >> $DAEMON_PIDS
884 #endif
889 #endif
885
890
886 #if windows git-server
891 #if windows git-server
887 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
892 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
888 #endif
893 #endif
889
894
890 #if hg-server
895 #if hg-server
891 $ hg init server2
896 $ hg init server2
892 $ hg --config "lfs.usercache=$TESTTMP/servercache2" -R server2 serve -d \
897 $ hg --config "lfs.usercache=$TESTTMP/servercache2" -R server2 serve -d \
893 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
898 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
894 $ cat hg.pid >> $DAEMON_PIDS
899 $ cat hg.pid >> $DAEMON_PIDS
895 #endif
900 #endif
896
901
897 $ cd $TESTTMP
902 $ cd $TESTTMP
898 $ hg --debug clone test test2
903 $ hg --debug clone test test2
899 http auth: user foo, password ***
904 http auth: user foo, password ***
900 linked 6 files
905 linked 6 files
901 http auth: user foo, password ***
906 http auth: user foo, password ***
902 updating to branch default
907 updating to branch default
903 resolving manifests
908 resolving manifests
904 branchmerge: False, force: False, partial: False
909 branchmerge: False, force: False, partial: False
905 ancestor: 000000000000, local: 000000000000+, remote: d2a338f184a8
910 ancestor: 000000000000, local: 000000000000+, remote: d2a338f184a8
906 http auth: user foo, password ***
911 http auth: user foo, password ***
907 Status: 200
912 Status: 200
908 Content-Length: 308 (git-server !)
913 Content-Length: 308 (git-server !)
909 Content-Length: 186 (hg-server !)
914 Content-Length: 186 (hg-server !)
910 Content-Type: application/vnd.git-lfs+json
915 Content-Type: application/vnd.git-lfs+json
911 Date: $HTTP_DATE$
916 Date: $HTTP_DATE$
912 Server: testing stub value (hg-server !)
917 Server: testing stub value (hg-server !)
913 {
918 {
914 "objects": [
919 "objects": [
915 {
920 {
916 "actions": { (git-server !)
921 "actions": { (git-server !)
917 "upload": { (git-server !)
922 "upload": { (git-server !)
918 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
923 "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
919 "header": { (git-server !)
924 "header": { (git-server !)
920 "Accept": "application/vnd.git-lfs" (git-server !)
925 "Accept": "application/vnd.git-lfs" (git-server !)
921 } (git-server !)
926 } (git-server !)
922 "href": "http://localhost:$HGPORT/objects/bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a" (git-server !)
927 "href": "http://localhost:$HGPORT/objects/bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a" (git-server !)
923 } (git-server !)
928 } (git-server !)
924 "error": { (hg-server !)
929 "error": { (hg-server !)
925 "code": 404 (hg-server !)
930 "code": 404 (hg-server !)
926 "message": "The object does not exist" (hg-server !)
931 "message": "The object does not exist" (hg-server !)
927 }
932 }
928 "oid": "bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a"
933 "oid": "bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a"
929 "size": 6
934 "size": 6
930 }
935 }
931 ]
936 ]
932 "transfer": "basic" (hg-server !)
937 "transfer": "basic" (hg-server !)
933 }
938 }
934 abort: LFS server error for "a": The object does not exist!
939 abort: LFS server error for "a": The object does not exist!
935 [255]
940 [255]
936
941
937 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
942 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
General Comments 0
You need to be logged in to leave comments. Login now