Mercurial > hg
comparison hgext/largefiles/overrides.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 749ef8c31187 |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
12 import copy | 12 import copy |
13 import os | 13 import os |
14 | 14 |
15 from mercurial.i18n import _ | 15 from mercurial.i18n import _ |
16 | 16 |
17 from mercurial.hgweb import ( | 17 from mercurial.hgweb import webcommands |
18 webcommands, | |
19 ) | |
20 | 18 |
21 from mercurial import ( | 19 from mercurial import ( |
22 archival, | 20 archival, |
23 cmdutil, | 21 cmdutil, |
24 copies as copiesmod, | 22 copies as copiesmod, |
49 | 47 |
50 eh = exthelper.exthelper() | 48 eh = exthelper.exthelper() |
51 | 49 |
52 # -- Utility functions: commonly/repeatedly needed functionality --------------- | 50 # -- Utility functions: commonly/repeatedly needed functionality --------------- |
53 | 51 |
52 | |
54 def composelargefilematcher(match, manifest): | 53 def composelargefilematcher(match, manifest): |
55 '''create a matcher that matches only the largefiles in the original | 54 '''create a matcher that matches only the largefiles in the original |
56 matcher''' | 55 matcher''' |
57 m = copy.copy(match) | 56 m = copy.copy(match) |
58 lfile = lambda f: lfutil.standin(f) in manifest | 57 lfile = lambda f: lfutil.standin(f) in manifest |
61 m.always = lambda: False | 60 m.always = lambda: False |
62 origmatchfn = m.matchfn | 61 origmatchfn = m.matchfn |
63 m.matchfn = lambda f: lfile(f) and origmatchfn(f) | 62 m.matchfn = lambda f: lfile(f) and origmatchfn(f) |
64 return m | 63 return m |
65 | 64 |
65 | |
66 def composenormalfilematcher(match, manifest, exclude=None): | 66 def composenormalfilematcher(match, manifest, exclude=None): |
67 excluded = set() | 67 excluded = set() |
68 if exclude is not None: | 68 if exclude is not None: |
69 excluded.update(exclude) | 69 excluded.update(exclude) |
70 | 70 |
71 m = copy.copy(match) | 71 m = copy.copy(match) |
72 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in | 72 notlfile = lambda f: not ( |
73 manifest or f in excluded) | 73 lfutil.isstandin(f) or lfutil.standin(f) in manifest or f in excluded |
74 ) | |
74 m._files = [lf for lf in m._files if notlfile(lf)] | 75 m._files = [lf for lf in m._files if notlfile(lf)] |
75 m._fileset = set(m._files) | 76 m._fileset = set(m._files) |
76 m.always = lambda: False | 77 m.always = lambda: False |
77 origmatchfn = m.matchfn | 78 origmatchfn = m.matchfn |
78 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) | 79 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) |
79 return m | 80 return m |
80 | 81 |
82 | |
81 def addlargefiles(ui, repo, isaddremove, matcher, uipathfn, **opts): | 83 def addlargefiles(ui, repo, isaddremove, matcher, uipathfn, **opts): |
82 large = opts.get(r'large') | 84 large = opts.get(r'large') |
83 lfsize = lfutil.getminsize( | 85 lfsize = lfutil.getminsize( |
84 ui, lfutil.islfilesrepo(repo), opts.get(r'lfsize')) | 86 ui, lfutil.islfilesrepo(repo), opts.get(r'lfsize') |
87 ) | |
85 | 88 |
86 lfmatcher = None | 89 lfmatcher = None |
87 if lfutil.islfilesrepo(repo): | 90 if lfutil.islfilesrepo(repo): |
88 lfpats = ui.configlist(lfutil.longname, 'patterns') | 91 lfpats = ui.configlist(lfutil.longname, 'patterns') |
89 if lfpats: | 92 if lfpats: |
110 # In case the file was removed previously, but not committed | 113 # In case the file was removed previously, but not committed |
111 # (issue3507) | 114 # (issue3507) |
112 if not repo.wvfs.exists(f): | 115 if not repo.wvfs.exists(f): |
113 continue | 116 continue |
114 | 117 |
115 abovemin = (lfsize and | 118 abovemin = ( |
116 repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024) | 119 lfsize and repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024 |
120 ) | |
117 if large or abovemin or (lfmatcher and lfmatcher(f)): | 121 if large or abovemin or (lfmatcher and lfmatcher(f)): |
118 lfnames.append(f) | 122 lfnames.append(f) |
119 if ui.verbose or not exact: | 123 if ui.verbose or not exact: |
120 ui.status(_('adding %s as a largefile\n') % uipathfn(f)) | 124 ui.status(_('adding %s as a largefile\n') % uipathfn(f)) |
121 | 125 |
127 if not opts.get(r'dry_run'): | 131 if not opts.get(r'dry_run'): |
128 standins = [] | 132 standins = [] |
129 lfdirstate = lfutil.openlfdirstate(ui, repo) | 133 lfdirstate = lfutil.openlfdirstate(ui, repo) |
130 for f in lfnames: | 134 for f in lfnames: |
131 standinname = lfutil.standin(f) | 135 standinname = lfutil.standin(f) |
132 lfutil.writestandin(repo, standinname, hash='', | 136 lfutil.writestandin( |
133 executable=lfutil.getexecutable(repo.wjoin(f))) | 137 repo, |
138 standinname, | |
139 hash='', | |
140 executable=lfutil.getexecutable(repo.wjoin(f)), | |
141 ) | |
134 standins.append(standinname) | 142 standins.append(standinname) |
135 if lfdirstate[f] == 'r': | 143 if lfdirstate[f] == 'r': |
136 lfdirstate.normallookup(f) | 144 lfdirstate.normallookup(f) |
137 else: | 145 else: |
138 lfdirstate.add(f) | 146 lfdirstate.add(f) |
139 lfdirstate.write() | 147 lfdirstate.write() |
140 bad += [lfutil.splitstandin(f) | 148 bad += [ |
141 for f in repo[None].add(standins) | 149 lfutil.splitstandin(f) |
142 if f in m.files()] | 150 for f in repo[None].add(standins) |
151 if f in m.files() | |
152 ] | |
143 | 153 |
144 added = [f for f in lfnames if f not in bad] | 154 added = [f for f in lfnames if f not in bad] |
145 return added, bad | 155 return added, bad |
156 | |
146 | 157 |
147 def removelargefiles(ui, repo, isaddremove, matcher, uipathfn, dryrun, **opts): | 158 def removelargefiles(ui, repo, isaddremove, matcher, uipathfn, dryrun, **opts): |
148 after = opts.get(r'after') | 159 after = opts.get(r'after') |
149 m = composelargefilematcher(matcher, repo[None].manifest()) | 160 m = composelargefilematcher(matcher, repo[None].manifest()) |
150 try: | 161 try: |
151 repo.lfstatus = True | 162 repo.lfstatus = True |
152 s = repo.status(match=m, clean=not isaddremove) | 163 s = repo.status(match=m, clean=not isaddremove) |
153 finally: | 164 finally: |
154 repo.lfstatus = False | 165 repo.lfstatus = False |
155 manifest = repo[None].manifest() | 166 manifest = repo[None].manifest() |
156 modified, added, deleted, clean = [[f for f in list | 167 modified, added, deleted, clean = [ |
157 if lfutil.standin(f) in manifest] | 168 [f for f in list if lfutil.standin(f) in manifest] |
158 for list in (s.modified, s.added, | 169 for list in (s.modified, s.added, s.deleted, s.clean) |
159 s.deleted, s.clean)] | 170 ] |
160 | 171 |
161 def warn(files, msg): | 172 def warn(files, msg): |
162 for f in files: | 173 for f in files: |
163 ui.warn(msg % uipathfn(f)) | 174 ui.warn(msg % uipathfn(f)) |
164 return int(len(files) > 0) | 175 return int(len(files) > 0) |
165 | 176 |
166 if after: | 177 if after: |
167 remove = deleted | 178 remove = deleted |
168 result = warn(modified + added + clean, | 179 result = warn( |
169 _('not removing %s: file still exists\n')) | 180 modified + added + clean, _('not removing %s: file still exists\n') |
181 ) | |
170 else: | 182 else: |
171 remove = deleted + clean | 183 remove = deleted + clean |
172 result = warn(modified, _('not removing %s: file is modified (use -f' | 184 result = warn( |
173 ' to force removal)\n')) | 185 modified, |
174 result = warn(added, _('not removing %s: file has been marked for add' | 186 _( |
175 ' (use forget to undo)\n')) or result | 187 'not removing %s: file is modified (use -f' |
188 ' to force removal)\n' | |
189 ), | |
190 ) | |
191 result = ( | |
192 warn( | |
193 added, | |
194 _( | |
195 'not removing %s: file has been marked for add' | |
196 ' (use forget to undo)\n' | |
197 ), | |
198 ) | |
199 or result | |
200 ) | |
176 | 201 |
177 # Need to lock because standin files are deleted then removed from the | 202 # Need to lock because standin files are deleted then removed from the |
178 # repository and we could race in-between. | 203 # repository and we could race in-between. |
179 with repo.wlock(): | 204 with repo.wlock(): |
180 lfdirstate = lfutil.openlfdirstate(ui, repo) | 205 lfdirstate = lfutil.openlfdirstate(ui, repo) |
196 for f in remove: | 221 for f in remove: |
197 repo.wvfs.unlinkpath(f, ignoremissing=True) | 222 repo.wvfs.unlinkpath(f, ignoremissing=True) |
198 repo[None].forget(remove) | 223 repo[None].forget(remove) |
199 | 224 |
200 for f in remove: | 225 for f in remove: |
201 lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f), | 226 lfutil.synclfdirstate( |
202 False) | 227 repo, lfdirstate, lfutil.splitstandin(f), False |
228 ) | |
203 | 229 |
204 lfdirstate.write() | 230 lfdirstate.write() |
205 | 231 |
206 return result | 232 return result |
233 | |
207 | 234 |
208 # For overriding mercurial.hgweb.webcommands so that largefiles will | 235 # For overriding mercurial.hgweb.webcommands so that largefiles will |
209 # appear at their right place in the manifests. | 236 # appear at their right place in the manifests. |
210 @eh.wrapfunction(webcommands, 'decodepath') | 237 @eh.wrapfunction(webcommands, 'decodepath') |
211 def decodepath(orig, path): | 238 def decodepath(orig, path): |
212 return lfutil.splitstandin(path) or path | 239 return lfutil.splitstandin(path) or path |
213 | 240 |
241 | |
214 # -- Wrappers: modify existing commands -------------------------------- | 242 # -- Wrappers: modify existing commands -------------------------------- |
215 | 243 |
216 @eh.wrapcommand('add', | 244 |
217 opts=[('', 'large', None, _('add as largefile')), | 245 @eh.wrapcommand( |
218 ('', 'normal', None, _('add as normal file')), | 246 'add', |
219 ('', 'lfsize', '', _('add all files above this size (in megabytes) ' | 247 opts=[ |
220 'as largefiles (default: 10)'))]) | 248 ('', 'large', None, _('add as largefile')), |
249 ('', 'normal', None, _('add as normal file')), | |
250 ( | |
251 '', | |
252 'lfsize', | |
253 '', | |
254 _( | |
255 'add all files above this size (in megabytes) ' | |
256 'as largefiles (default: 10)' | |
257 ), | |
258 ), | |
259 ], | |
260 ) | |
221 def overrideadd(orig, ui, repo, *pats, **opts): | 261 def overrideadd(orig, ui, repo, *pats, **opts): |
222 if opts.get(r'normal') and opts.get(r'large'): | 262 if opts.get(r'normal') and opts.get(r'large'): |
223 raise error.Abort(_('--normal cannot be used with --large')) | 263 raise error.Abort(_('--normal cannot be used with --large')) |
224 return orig(ui, repo, *pats, **opts) | 264 return orig(ui, repo, *pats, **opts) |
265 | |
225 | 266 |
226 @eh.wrapfunction(cmdutil, 'add') | 267 @eh.wrapfunction(cmdutil, 'add') |
227 def cmdutiladd(orig, ui, repo, matcher, prefix, uipathfn, explicitonly, **opts): | 268 def cmdutiladd(orig, ui, repo, matcher, prefix, uipathfn, explicitonly, **opts): |
228 # The --normal flag short circuits this override | 269 # The --normal flag short circuits this override |
229 if opts.get(r'normal'): | 270 if opts.get(r'normal'): |
230 return orig(ui, repo, matcher, prefix, uipathfn, explicitonly, **opts) | 271 return orig(ui, repo, matcher, prefix, uipathfn, explicitonly, **opts) |
231 | 272 |
232 ladded, lbad = addlargefiles(ui, repo, False, matcher, uipathfn, **opts) | 273 ladded, lbad = addlargefiles(ui, repo, False, matcher, uipathfn, **opts) |
233 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(), | 274 normalmatcher = composenormalfilematcher( |
234 ladded) | 275 matcher, repo[None].manifest(), ladded |
276 ) | |
235 bad = orig(ui, repo, normalmatcher, prefix, uipathfn, explicitonly, **opts) | 277 bad = orig(ui, repo, normalmatcher, prefix, uipathfn, explicitonly, **opts) |
236 | 278 |
237 bad.extend(f for f in lbad) | 279 bad.extend(f for f in lbad) |
238 return bad | 280 return bad |
239 | 281 |
282 | |
240 @eh.wrapfunction(cmdutil, 'remove') | 283 @eh.wrapfunction(cmdutil, 'remove') |
241 def cmdutilremove(orig, ui, repo, matcher, prefix, uipathfn, after, force, | 284 def cmdutilremove( |
242 subrepos, dryrun): | 285 orig, ui, repo, matcher, prefix, uipathfn, after, force, subrepos, dryrun |
286 ): | |
243 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest()) | 287 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest()) |
244 result = orig(ui, repo, normalmatcher, prefix, uipathfn, after, force, | 288 result = orig( |
245 subrepos, dryrun) | 289 ui, |
246 return removelargefiles(ui, repo, False, matcher, uipathfn, dryrun, | 290 repo, |
247 after=after, force=force) or result | 291 normalmatcher, |
292 prefix, | |
293 uipathfn, | |
294 after, | |
295 force, | |
296 subrepos, | |
297 dryrun, | |
298 ) | |
299 return ( | |
300 removelargefiles( | |
301 ui, repo, False, matcher, uipathfn, dryrun, after=after, force=force | |
302 ) | |
303 or result | |
304 ) | |
305 | |
248 | 306 |
249 @eh.wrapfunction(subrepo.hgsubrepo, 'status') | 307 @eh.wrapfunction(subrepo.hgsubrepo, 'status') |
250 def overridestatusfn(orig, repo, rev2, **opts): | 308 def overridestatusfn(orig, repo, rev2, **opts): |
251 try: | 309 try: |
252 repo._repo.lfstatus = True | 310 repo._repo.lfstatus = True |
253 return orig(repo, rev2, **opts) | 311 return orig(repo, rev2, **opts) |
254 finally: | 312 finally: |
255 repo._repo.lfstatus = False | 313 repo._repo.lfstatus = False |
256 | 314 |
315 | |
257 @eh.wrapcommand('status') | 316 @eh.wrapcommand('status') |
258 def overridestatus(orig, ui, repo, *pats, **opts): | 317 def overridestatus(orig, ui, repo, *pats, **opts): |
259 try: | 318 try: |
260 repo.lfstatus = True | 319 repo.lfstatus = True |
261 return orig(ui, repo, *pats, **opts) | 320 return orig(ui, repo, *pats, **opts) |
262 finally: | 321 finally: |
263 repo.lfstatus = False | 322 repo.lfstatus = False |
264 | 323 |
324 | |
265 @eh.wrapfunction(subrepo.hgsubrepo, 'dirty') | 325 @eh.wrapfunction(subrepo.hgsubrepo, 'dirty') |
266 def overridedirty(orig, repo, ignoreupdate=False, missing=False): | 326 def overridedirty(orig, repo, ignoreupdate=False, missing=False): |
267 try: | 327 try: |
268 repo._repo.lfstatus = True | 328 repo._repo.lfstatus = True |
269 return orig(repo, ignoreupdate=ignoreupdate, missing=missing) | 329 return orig(repo, ignoreupdate=ignoreupdate, missing=missing) |
270 finally: | 330 finally: |
271 repo._repo.lfstatus = False | 331 repo._repo.lfstatus = False |
272 | 332 |
333 | |
273 @eh.wrapcommand('log') | 334 @eh.wrapcommand('log') |
274 def overridelog(orig, ui, repo, *pats, **opts): | 335 def overridelog(orig, ui, repo, *pats, **opts): |
275 def overridematchandpats(orig, ctx, pats=(), opts=None, globbed=False, | 336 def overridematchandpats( |
276 default='relpath', badfn=None): | 337 orig, |
338 ctx, | |
339 pats=(), | |
340 opts=None, | |
341 globbed=False, | |
342 default='relpath', | |
343 badfn=None, | |
344 ): | |
277 """Matcher that merges root directory with .hglf, suitable for log. | 345 """Matcher that merges root directory with .hglf, suitable for log. |
278 It is still possible to match .hglf directly. | 346 It is still possible to match .hglf directly. |
279 For any listed files run log on the standin too. | 347 For any listed files run log on the standin too. |
280 matchfn tries both the given filename and with .hglf stripped. | 348 matchfn tries both the given filename and with .hglf stripped. |
281 """ | 349 """ |
302 return tostandin(kindpat[1]) | 370 return tostandin(kindpat[1]) |
303 | 371 |
304 cwd = repo.getcwd() | 372 cwd = repo.getcwd() |
305 if cwd: | 373 if cwd: |
306 hglf = lfutil.shortname | 374 hglf = lfutil.shortname |
307 back = util.pconvert(repo.pathto(hglf)[:-len(hglf)]) | 375 back = util.pconvert(repo.pathto(hglf)[: -len(hglf)]) |
308 | 376 |
309 def tostandin(f): | 377 def tostandin(f): |
310 # The file may already be a standin, so truncate the back | 378 # The file may already be a standin, so truncate the back |
311 # prefix and test before mangling it. This avoids turning | 379 # prefix and test before mangling it. This avoids turning |
312 # 'glob:../.hglf/foo*' into 'glob:../.hglf/../.hglf/foo*'. | 380 # 'glob:../.hglf/foo*' into 'glob:../.hglf/../.hglf/foo*'. |
313 if f.startswith(back) and lfutil.splitstandin(f[len(back):]): | 381 if f.startswith(back) and lfutil.splitstandin(f[len(back) :]): |
314 return f | 382 return f |
315 | 383 |
316 # An absolute path is from outside the repo, so truncate the | 384 # An absolute path is from outside the repo, so truncate the |
317 # path to the root before building the standin. Otherwise cwd | 385 # path to the root before building the standin. Otherwise cwd |
318 # is somewhere in the repo, relative to root, and needs to be | 386 # is somewhere in the repo, relative to root, and needs to be |
319 # prepended before building the standin. | 387 # prepended before building the standin. |
320 if os.path.isabs(cwd): | 388 if os.path.isabs(cwd): |
321 f = f[len(back):] | 389 f = f[len(back) :] |
322 else: | 390 else: |
323 f = cwd + '/' + f | 391 f = cwd + '/' + f |
324 return back + lfutil.standin(f) | 392 return back + lfutil.standin(f) |
393 | |
325 else: | 394 else: |
395 | |
326 def tostandin(f): | 396 def tostandin(f): |
327 if lfutil.isstandin(f): | 397 if lfutil.isstandin(f): |
328 return f | 398 return f |
329 return lfutil.standin(f) | 399 return lfutil.standin(f) |
400 | |
330 pats.update(fixpats(f, tostandin) for f in p) | 401 pats.update(fixpats(f, tostandin) for f in p) |
331 | 402 |
332 for i in range(0, len(m._files)): | 403 for i in range(0, len(m._files)): |
333 # Don't add '.hglf' to m.files, since that is already covered by '.' | 404 # Don't add '.hglf' to m.files, since that is already covered by '.' |
334 if m._files[i] == '.': | 405 if m._files[i] == '.': |
344 m._files.append(standin) | 415 m._files.append(standin) |
345 | 416 |
346 m._fileset = set(m._files) | 417 m._fileset = set(m._files) |
347 m.always = lambda: False | 418 m.always = lambda: False |
348 origmatchfn = m.matchfn | 419 origmatchfn = m.matchfn |
420 | |
349 def lfmatchfn(f): | 421 def lfmatchfn(f): |
350 lf = lfutil.splitstandin(f) | 422 lf = lfutil.splitstandin(f) |
351 if lf is not None and origmatchfn(lf): | 423 if lf is not None and origmatchfn(lf): |
352 return True | 424 return True |
353 r = origmatchfn(f) | 425 r = origmatchfn(f) |
354 return r | 426 return r |
427 | |
355 m.matchfn = lfmatchfn | 428 m.matchfn = lfmatchfn |
356 | 429 |
357 ui.debug('updated patterns: %s\n' % ', '.join(sorted(pats))) | 430 ui.debug('updated patterns: %s\n' % ', '.join(sorted(pats))) |
358 return m, pats | 431 return m, pats |
359 | 432 |
361 # (1) to determine what revisions should be printed out, and | 434 # (1) to determine what revisions should be printed out, and |
362 # (2) to determine what files to print out diffs for. | 435 # (2) to determine what files to print out diffs for. |
363 # The magic matchandpats override should be used for case (1) but not for | 436 # The magic matchandpats override should be used for case (1) but not for |
364 # case (2). | 437 # case (2). |
365 oldmatchandpats = scmutil.matchandpats | 438 oldmatchandpats = scmutil.matchandpats |
439 | |
366 def overridemakefilematcher(orig, repo, pats, opts, badfn=None): | 440 def overridemakefilematcher(orig, repo, pats, opts, badfn=None): |
367 wctx = repo[None] | 441 wctx = repo[None] |
368 match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn) | 442 match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn) |
369 return lambda ctx: match | 443 return lambda ctx: match |
370 | 444 |
371 wrappedmatchandpats = extensions.wrappedfunction(scmutil, 'matchandpats', | 445 wrappedmatchandpats = extensions.wrappedfunction( |
372 overridematchandpats) | 446 scmutil, 'matchandpats', overridematchandpats |
447 ) | |
373 wrappedmakefilematcher = extensions.wrappedfunction( | 448 wrappedmakefilematcher = extensions.wrappedfunction( |
374 logcmdutil, '_makenofollowfilematcher', overridemakefilematcher) | 449 logcmdutil, '_makenofollowfilematcher', overridemakefilematcher |
450 ) | |
375 with wrappedmatchandpats, wrappedmakefilematcher: | 451 with wrappedmatchandpats, wrappedmakefilematcher: |
376 return orig(ui, repo, *pats, **opts) | 452 return orig(ui, repo, *pats, **opts) |
377 | 453 |
378 @eh.wrapcommand('verify', | 454 |
379 opts=[('', 'large', None, | 455 @eh.wrapcommand( |
380 _('verify that all largefiles in current revision exists')), | 456 'verify', |
381 ('', 'lfa', None, | 457 opts=[ |
382 _('verify largefiles in all revisions, not just current')), | 458 ( |
383 ('', 'lfc', None, | 459 '', |
384 _('verify local largefile contents, not just existence'))]) | 460 'large', |
461 None, | |
462 _('verify that all largefiles in current revision exists'), | |
463 ), | |
464 ( | |
465 '', | |
466 'lfa', | |
467 None, | |
468 _('verify largefiles in all revisions, not just current'), | |
469 ), | |
470 ( | |
471 '', | |
472 'lfc', | |
473 None, | |
474 _('verify local largefile contents, not just existence'), | |
475 ), | |
476 ], | |
477 ) | |
385 def overrideverify(orig, ui, repo, *pats, **opts): | 478 def overrideverify(orig, ui, repo, *pats, **opts): |
386 large = opts.pop(r'large', False) | 479 large = opts.pop(r'large', False) |
387 all = opts.pop(r'lfa', False) | 480 all = opts.pop(r'lfa', False) |
388 contents = opts.pop(r'lfc', False) | 481 contents = opts.pop(r'lfc', False) |
389 | 482 |
390 result = orig(ui, repo, *pats, **opts) | 483 result = orig(ui, repo, *pats, **opts) |
391 if large or all or contents: | 484 if large or all or contents: |
392 result = result or lfcommands.verifylfiles(ui, repo, all, contents) | 485 result = result or lfcommands.verifylfiles(ui, repo, all, contents) |
393 return result | 486 return result |
394 | 487 |
395 @eh.wrapcommand('debugstate', | 488 |
396 opts=[('', 'large', None, _('display largefiles dirstate'))]) | 489 @eh.wrapcommand( |
490 'debugstate', opts=[('', 'large', None, _('display largefiles dirstate'))] | |
491 ) | |
397 def overridedebugstate(orig, ui, repo, *pats, **opts): | 492 def overridedebugstate(orig, ui, repo, *pats, **opts): |
398 large = opts.pop(r'large', False) | 493 large = opts.pop(r'large', False) |
399 if large: | 494 if large: |
495 | |
400 class fakerepo(object): | 496 class fakerepo(object): |
401 dirstate = lfutil.openlfdirstate(ui, repo) | 497 dirstate = lfutil.openlfdirstate(ui, repo) |
498 | |
402 orig(ui, fakerepo, *pats, **opts) | 499 orig(ui, fakerepo, *pats, **opts) |
403 else: | 500 else: |
404 orig(ui, repo, *pats, **opts) | 501 orig(ui, repo, *pats, **opts) |
502 | |
405 | 503 |
406 # Before starting the manifest merge, merge.updates will call | 504 # Before starting the manifest merge, merge.updates will call |
407 # _checkunknownfile to check if there are any files in the merged-in | 505 # _checkunknownfile to check if there are any files in the merged-in |
408 # changeset that collide with unknown files in the working copy. | 506 # changeset that collide with unknown files in the working copy. |
409 # | 507 # |
416 @eh.wrapfunction(merge, '_checkunknownfile') | 514 @eh.wrapfunction(merge, '_checkunknownfile') |
417 def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None): | 515 def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None): |
418 if lfutil.standin(repo.dirstate.normalize(f)) in wctx: | 516 if lfutil.standin(repo.dirstate.normalize(f)) in wctx: |
419 return False | 517 return False |
420 return origfn(repo, wctx, mctx, f, f2) | 518 return origfn(repo, wctx, mctx, f, f2) |
519 | |
421 | 520 |
422 # The manifest merge handles conflicts on the manifest level. We want | 521 # The manifest merge handles conflicts on the manifest level. We want |
423 # to handle changes in largefile-ness of files at this level too. | 522 # to handle changes in largefile-ness of files at this level too. |
424 # | 523 # |
425 # The strategy is to run the original calculateupdates and then process | 524 # The strategy is to run the original calculateupdates and then process |
444 # | 543 # |
445 # Finally, the merge.applyupdates function will then take care of | 544 # Finally, the merge.applyupdates function will then take care of |
446 # writing the files into the working copy and lfcommands.updatelfiles | 545 # writing the files into the working copy and lfcommands.updatelfiles |
447 # will update the largefiles. | 546 # will update the largefiles. |
448 @eh.wrapfunction(merge, 'calculateupdates') | 547 @eh.wrapfunction(merge, 'calculateupdates') |
449 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force, | 548 def overridecalculateupdates( |
450 acceptremote, *args, **kwargs): | 549 origfn, repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs |
550 ): | |
451 overwrite = force and not branchmerge | 551 overwrite = force and not branchmerge |
452 actions, diverge, renamedelete = origfn( | 552 actions, diverge, renamedelete = origfn( |
453 repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs) | 553 repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs |
554 ) | |
454 | 555 |
455 if overwrite: | 556 if overwrite: |
456 return actions, diverge, renamedelete | 557 return actions, diverge, renamedelete |
457 | 558 |
458 # Convert to dictionary with filename as key and action as value. | 559 # Convert to dictionary with filename as key and action as value. |
472 if sm == 'dc': | 573 if sm == 'dc': |
473 f1, f2, fa, move, anc = sargs | 574 f1, f2, fa, move, anc = sargs |
474 sargs = (p2[f2].flags(), False) | 575 sargs = (p2[f2].flags(), False) |
475 # Case 1: normal file in the working copy, largefile in | 576 # Case 1: normal file in the working copy, largefile in |
476 # the second parent | 577 # the second parent |
477 usermsg = _('remote turned local normal file %s into a largefile\n' | 578 usermsg = ( |
478 'use (l)argefile or keep (n)ormal file?' | 579 _( |
479 '$$ &Largefile $$ &Normal file') % lfile | 580 'remote turned local normal file %s into a largefile\n' |
480 if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile | 581 'use (l)argefile or keep (n)ormal file?' |
582 '$$ &Largefile $$ &Normal file' | |
583 ) | |
584 % lfile | |
585 ) | |
586 if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile | |
481 actions[lfile] = ('r', None, 'replaced by standin') | 587 actions[lfile] = ('r', None, 'replaced by standin') |
482 actions[standin] = ('g', sargs, 'replaces standin') | 588 actions[standin] = ('g', sargs, 'replaces standin') |
483 else: # keep local normal file | 589 else: # keep local normal file |
484 actions[lfile] = ('k', None, 'replaces standin') | 590 actions[lfile] = ('k', None, 'replaces standin') |
485 if branchmerge: | 591 if branchmerge: |
486 actions[standin] = ('k', None, 'replaced by non-standin') | 592 actions[standin] = ('k', None, 'replaced by non-standin') |
487 else: | 593 else: |
488 actions[standin] = ('r', None, 'replaced by non-standin') | 594 actions[standin] = ('r', None, 'replaced by non-standin') |
490 if lm == 'dc': | 596 if lm == 'dc': |
491 f1, f2, fa, move, anc = largs | 597 f1, f2, fa, move, anc = largs |
492 largs = (p2[f2].flags(), False) | 598 largs = (p2[f2].flags(), False) |
493 # Case 2: largefile in the working copy, normal file in | 599 # Case 2: largefile in the working copy, normal file in |
494 # the second parent | 600 # the second parent |
495 usermsg = _('remote turned local largefile %s into a normal file\n' | 601 usermsg = ( |
602 _( | |
603 'remote turned local largefile %s into a normal file\n' | |
496 'keep (l)argefile or use (n)ormal file?' | 604 'keep (l)argefile or use (n)ormal file?' |
497 '$$ &Largefile $$ &Normal file') % lfile | 605 '$$ &Largefile $$ &Normal file' |
498 if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile | 606 ) |
607 % lfile | |
608 ) | |
609 if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile | |
499 if branchmerge: | 610 if branchmerge: |
500 # largefile can be restored from standin safely | 611 # largefile can be restored from standin safely |
501 actions[lfile] = ('k', None, 'replaced by standin') | 612 actions[lfile] = ('k', None, 'replaced by standin') |
502 actions[standin] = ('k', None, 'replaces standin') | 613 actions[standin] = ('k', None, 'replaces standin') |
503 else: | 614 else: |
504 # "lfile" should be marked as "removed" without | 615 # "lfile" should be marked as "removed" without |
505 # removal of itself | 616 # removal of itself |
506 actions[lfile] = ('lfmr', None, | 617 actions[lfile] = ( |
507 'forget non-standin largefile') | 618 'lfmr', |
619 None, | |
620 'forget non-standin largefile', | |
621 ) | |
508 | 622 |
509 # linear-merge should treat this largefile as 're-added' | 623 # linear-merge should treat this largefile as 're-added' |
510 actions[standin] = ('a', None, 'keep standin') | 624 actions[standin] = ('a', None, 'keep standin') |
511 else: # pick remote normal file | 625 else: # pick remote normal file |
512 actions[lfile] = ('g', largs, 'replaces standin') | 626 actions[lfile] = ('g', largs, 'replaces standin') |
513 actions[standin] = ('r', None, 'replaced by non-standin') | 627 actions[standin] = ('r', None, 'replaced by non-standin') |
514 | 628 |
515 return actions, diverge, renamedelete | 629 return actions, diverge, renamedelete |
630 | |
516 | 631 |
517 @eh.wrapfunction(merge, 'recordupdates') | 632 @eh.wrapfunction(merge, 'recordupdates') |
518 def mergerecordupdates(orig, repo, actions, branchmerge, getfiledata): | 633 def mergerecordupdates(orig, repo, actions, branchmerge, getfiledata): |
519 if 'lfmr' in actions: | 634 if 'lfmr' in actions: |
520 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | 635 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
526 lfdirstate.add(lfile) | 641 lfdirstate.add(lfile) |
527 lfdirstate.write() | 642 lfdirstate.write() |
528 | 643 |
529 return orig(repo, actions, branchmerge, getfiledata) | 644 return orig(repo, actions, branchmerge, getfiledata) |
530 | 645 |
646 | |
531 # Override filemerge to prompt the user about how they wish to merge | 647 # Override filemerge to prompt the user about how they wish to merge |
532 # largefiles. This will handle identical edits without prompting the user. | 648 # largefiles. This will handle identical edits without prompting the user. |
533 @eh.wrapfunction(filemerge, '_filemerge') | 649 @eh.wrapfunction(filemerge, '_filemerge') |
534 def overridefilemerge(origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, | 650 def overridefilemerge( |
535 labels=None): | 651 origfn, premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=None |
652 ): | |
536 if not lfutil.isstandin(orig) or fcd.isabsent() or fco.isabsent(): | 653 if not lfutil.isstandin(orig) or fcd.isabsent() or fco.isabsent(): |
537 return origfn(premerge, repo, wctx, mynode, orig, fcd, fco, fca, | 654 return origfn( |
538 labels=labels) | 655 premerge, repo, wctx, mynode, orig, fcd, fco, fca, labels=labels |
656 ) | |
539 | 657 |
540 ahash = lfutil.readasstandin(fca).lower() | 658 ahash = lfutil.readasstandin(fca).lower() |
541 dhash = lfutil.readasstandin(fcd).lower() | 659 dhash = lfutil.readasstandin(fcd).lower() |
542 ohash = lfutil.readasstandin(fco).lower() | 660 ohash = lfutil.readasstandin(fco).lower() |
543 if (ohash != ahash and | 661 if ( |
544 ohash != dhash and | 662 ohash != ahash |
545 (dhash == ahash or | 663 and ohash != dhash |
546 repo.ui.promptchoice( | 664 and ( |
547 _('largefile %s has a merge conflict\nancestor was %s\n' | 665 dhash == ahash |
548 'you can keep (l)ocal %s or take (o)ther %s.\n' | 666 or repo.ui.promptchoice( |
549 'what do you want to do?' | 667 _( |
550 '$$ &Local $$ &Other') % | 668 'largefile %s has a merge conflict\nancestor was %s\n' |
551 (lfutil.splitstandin(orig), ahash, dhash, ohash), | 669 'you can keep (l)ocal %s or take (o)ther %s.\n' |
552 0) == 1)): | 670 'what do you want to do?' |
671 '$$ &Local $$ &Other' | |
672 ) | |
673 % (lfutil.splitstandin(orig), ahash, dhash, ohash), | |
674 0, | |
675 ) | |
676 == 1 | |
677 ) | |
678 ): | |
553 repo.wwrite(fcd.path(), fco.data(), fco.flags()) | 679 repo.wwrite(fcd.path(), fco.data(), fco.flags()) |
554 return True, 0, False | 680 return True, 0, False |
681 | |
555 | 682 |
556 @eh.wrapfunction(copiesmod, 'pathcopies') | 683 @eh.wrapfunction(copiesmod, 'pathcopies') |
557 def copiespathcopies(orig, ctx1, ctx2, match=None): | 684 def copiespathcopies(orig, ctx1, ctx2, match=None): |
558 copies = orig(ctx1, ctx2, match=match) | 685 copies = orig(ctx1, ctx2, match=match) |
559 updated = {} | 686 updated = {} |
560 | 687 |
561 for k, v in copies.iteritems(): | 688 for k, v in copies.iteritems(): |
562 updated[lfutil.splitstandin(k) or k] = lfutil.splitstandin(v) or v | 689 updated[lfutil.splitstandin(k) or k] = lfutil.splitstandin(v) or v |
563 | 690 |
564 return updated | 691 return updated |
692 | |
565 | 693 |
566 # Copy first changes the matchers to match standins instead of | 694 # Copy first changes the matchers to match standins instead of |
567 # largefiles. Then it overrides util.copyfile in that function it | 695 # largefiles. Then it overrides util.copyfile in that function it |
568 # checks if the destination largefile already exists. It also keeps a | 696 # checks if the destination largefile already exists. It also keeps a |
569 # list of copied files so that the largefiles can be copied and the | 697 # list of copied files so that the largefiles can be copied and the |
580 # only match normal files and run it, then replace it to just | 708 # only match normal files and run it, then replace it to just |
581 # match largefiles and run it again. | 709 # match largefiles and run it again. |
582 nonormalfiles = False | 710 nonormalfiles = False |
583 nolfiles = False | 711 nolfiles = False |
584 manifest = repo[None].manifest() | 712 manifest = repo[None].manifest() |
585 def normalfilesmatchfn(orig, ctx, pats=(), opts=None, globbed=False, | 713 |
586 default='relpath', badfn=None): | 714 def normalfilesmatchfn( |
715 orig, | |
716 ctx, | |
717 pats=(), | |
718 opts=None, | |
719 globbed=False, | |
720 default='relpath', | |
721 badfn=None, | |
722 ): | |
587 if opts is None: | 723 if opts is None: |
588 opts = {} | 724 opts = {} |
589 match = orig(ctx, pats, opts, globbed, default, badfn=badfn) | 725 match = orig(ctx, pats, opts, globbed, default, badfn=badfn) |
590 return composenormalfilematcher(match, manifest) | 726 return composenormalfilematcher(match, manifest) |
727 | |
591 with extensions.wrappedfunction(scmutil, 'match', normalfilesmatchfn): | 728 with extensions.wrappedfunction(scmutil, 'match', normalfilesmatchfn): |
592 try: | 729 try: |
593 result = orig(ui, repo, pats, opts, rename) | 730 result = orig(ui, repo, pats, opts, rename) |
594 except error.Abort as e: | 731 except error.Abort as e: |
595 if pycompat.bytestr(e) != _('no files to copy'): | 732 if pycompat.bytestr(e) != _('no files to copy'): |
620 # When we call orig below it creates the standins but we don't add | 757 # When we call orig below it creates the standins but we don't add |
621 # them to the dir state until later so lock during that time. | 758 # them to the dir state until later so lock during that time. |
622 wlock = repo.wlock() | 759 wlock = repo.wlock() |
623 | 760 |
624 manifest = repo[None].manifest() | 761 manifest = repo[None].manifest() |
625 def overridematch(orig, ctx, pats=(), opts=None, globbed=False, | 762 |
626 default='relpath', badfn=None): | 763 def overridematch( |
764 orig, | |
765 ctx, | |
766 pats=(), | |
767 opts=None, | |
768 globbed=False, | |
769 default='relpath', | |
770 badfn=None, | |
771 ): | |
627 if opts is None: | 772 if opts is None: |
628 opts = {} | 773 opts = {} |
629 newpats = [] | 774 newpats = [] |
630 # The patterns were previously mangled to add the standin | 775 # The patterns were previously mangled to add the standin |
631 # directory; we need to remove that now | 776 # directory; we need to remove that now |
638 m = copy.copy(match) | 783 m = copy.copy(match) |
639 lfile = lambda f: lfutil.standin(f) in manifest | 784 lfile = lambda f: lfutil.standin(f) in manifest |
640 m._files = [lfutil.standin(f) for f in m._files if lfile(f)] | 785 m._files = [lfutil.standin(f) for f in m._files if lfile(f)] |
641 m._fileset = set(m._files) | 786 m._fileset = set(m._files) |
642 origmatchfn = m.matchfn | 787 origmatchfn = m.matchfn |
788 | |
643 def matchfn(f): | 789 def matchfn(f): |
644 lfile = lfutil.splitstandin(f) | 790 lfile = lfutil.splitstandin(f) |
645 return (lfile is not None and | 791 return ( |
646 (f in manifest) and | 792 lfile is not None |
647 origmatchfn(lfile) or | 793 and (f in manifest) |
648 None) | 794 and origmatchfn(lfile) |
795 or None | |
796 ) | |
797 | |
649 m.matchfn = matchfn | 798 m.matchfn = matchfn |
650 return m | 799 return m |
800 | |
651 listpats = [] | 801 listpats = [] |
652 for pat in pats: | 802 for pat in pats: |
653 if matchmod.patkind(pat) is not None: | 803 if matchmod.patkind(pat) is not None: |
654 listpats.append(pat) | 804 listpats.append(pat) |
655 else: | 805 else: |
656 listpats.append(makestandin(pat)) | 806 listpats.append(makestandin(pat)) |
657 | 807 |
658 copiedfiles = [] | 808 copiedfiles = [] |
809 | |
659 def overridecopyfile(orig, src, dest, *args, **kwargs): | 810 def overridecopyfile(orig, src, dest, *args, **kwargs): |
660 if (lfutil.shortname in src and | 811 if lfutil.shortname in src and dest.startswith( |
661 dest.startswith(repo.wjoin(lfutil.shortname))): | 812 repo.wjoin(lfutil.shortname) |
813 ): | |
662 destlfile = dest.replace(lfutil.shortname, '') | 814 destlfile = dest.replace(lfutil.shortname, '') |
663 if not opts['force'] and os.path.exists(destlfile): | 815 if not opts['force'] and os.path.exists(destlfile): |
664 raise IOError('', | 816 raise IOError('', _('destination largefile already exists')) |
665 _('destination largefile already exists')) | |
666 copiedfiles.append((src, dest)) | 817 copiedfiles.append((src, dest)) |
667 orig(src, dest, *args, **kwargs) | 818 orig(src, dest, *args, **kwargs) |
819 | |
668 with extensions.wrappedfunction(util, 'copyfile', overridecopyfile): | 820 with extensions.wrappedfunction(util, 'copyfile', overridecopyfile): |
669 with extensions.wrappedfunction(scmutil, 'match', overridematch): | 821 with extensions.wrappedfunction(scmutil, 'match', overridematch): |
670 result += orig(ui, repo, listpats, opts, rename) | 822 result += orig(ui, repo, listpats, opts, rename) |
671 | 823 |
672 lfdirstate = lfutil.openlfdirstate(ui, repo) | 824 lfdirstate = lfutil.openlfdirstate(ui, repo) |
673 for (src, dest) in copiedfiles: | 825 for (src, dest) in copiedfiles: |
674 if (lfutil.shortname in src and | 826 if lfutil.shortname in src and dest.startswith( |
675 dest.startswith(repo.wjoin(lfutil.shortname))): | 827 repo.wjoin(lfutil.shortname) |
828 ): | |
676 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '') | 829 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '') |
677 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '') | 830 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '') |
678 destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or '.' | 831 destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or '.' |
679 if not os.path.isdir(destlfiledir): | 832 if not os.path.isdir(destlfiledir): |
680 os.makedirs(destlfiledir) | 833 os.makedirs(destlfiledir) |
684 # The file is gone, but this deletes any empty parent | 837 # The file is gone, but this deletes any empty parent |
685 # directories as a side-effect. | 838 # directories as a side-effect. |
686 repo.wvfs.unlinkpath(srclfile, ignoremissing=True) | 839 repo.wvfs.unlinkpath(srclfile, ignoremissing=True) |
687 lfdirstate.remove(srclfile) | 840 lfdirstate.remove(srclfile) |
688 else: | 841 else: |
689 util.copyfile(repo.wjoin(srclfile), | 842 util.copyfile(repo.wjoin(srclfile), repo.wjoin(destlfile)) |
690 repo.wjoin(destlfile)) | |
691 | 843 |
692 lfdirstate.add(destlfile) | 844 lfdirstate.add(destlfile) |
693 lfdirstate.write() | 845 lfdirstate.write() |
694 except error.Abort as e: | 846 except error.Abort as e: |
695 if pycompat.bytestr(e) != _('no files to copy'): | 847 if pycompat.bytestr(e) != _('no files to copy'): |
701 | 853 |
702 if nolfiles and nonormalfiles: | 854 if nolfiles and nonormalfiles: |
703 raise error.Abort(_('no files to copy')) | 855 raise error.Abort(_('no files to copy')) |
704 | 856 |
705 return result | 857 return result |
858 | |
706 | 859 |
707 # When the user calls revert, we have to be careful to not revert any | 860 # When the user calls revert, we have to be careful to not revert any |
708 # changes to other largefiles accidentally. This means we have to keep | 861 # changes to other largefiles accidentally. This means we have to keep |
709 # track of the largefiles that are being reverted so we only pull down | 862 # track of the largefiles that are being reverted so we only pull down |
710 # the necessary largefiles. | 863 # the necessary largefiles. |
724 lfdirstate.write() | 877 lfdirstate.write() |
725 for lfile in s.modified: | 878 for lfile in s.modified: |
726 lfutil.updatestandin(repo, lfile, lfutil.standin(lfile)) | 879 lfutil.updatestandin(repo, lfile, lfutil.standin(lfile)) |
727 for lfile in s.deleted: | 880 for lfile in s.deleted: |
728 fstandin = lfutil.standin(lfile) | 881 fstandin = lfutil.standin(lfile) |
729 if (repo.wvfs.exists(fstandin)): | 882 if repo.wvfs.exists(fstandin): |
730 repo.wvfs.unlink(fstandin) | 883 repo.wvfs.unlink(fstandin) |
731 | 884 |
732 oldstandins = lfutil.getstandinsstate(repo) | 885 oldstandins = lfutil.getstandinsstate(repo) |
733 | 886 |
734 def overridematch(orig, mctx, pats=(), opts=None, globbed=False, | 887 def overridematch( |
735 default='relpath', badfn=None): | 888 orig, |
889 mctx, | |
890 pats=(), | |
891 opts=None, | |
892 globbed=False, | |
893 default='relpath', | |
894 badfn=None, | |
895 ): | |
736 if opts is None: | 896 if opts is None: |
737 opts = {} | 897 opts = {} |
738 match = orig(mctx, pats, opts, globbed, default, badfn=badfn) | 898 match = orig(mctx, pats, opts, globbed, default, badfn=badfn) |
739 m = copy.copy(match) | 899 m = copy.copy(match) |
740 | 900 |
741 # revert supports recursing into subrepos, and though largefiles | 901 # revert supports recursing into subrepos, and though largefiles |
742 # currently doesn't work correctly in that case, this match is | 902 # currently doesn't work correctly in that case, this match is |
743 # called, so the lfdirstate above may not be the correct one for | 903 # called, so the lfdirstate above may not be the correct one for |
744 # this invocation of match. | 904 # this invocation of match. |
745 lfdirstate = lfutil.openlfdirstate(mctx.repo().ui, mctx.repo(), | 905 lfdirstate = lfutil.openlfdirstate( |
746 False) | 906 mctx.repo().ui, mctx.repo(), False |
907 ) | |
747 | 908 |
748 wctx = repo[None] | 909 wctx = repo[None] |
749 matchfiles = [] | 910 matchfiles = [] |
750 for f in m._files: | 911 for f in m._files: |
751 standin = lfutil.standin(f) | 912 standin = lfutil.standin(f) |
756 else: | 917 else: |
757 matchfiles.append(f) | 918 matchfiles.append(f) |
758 m._files = matchfiles | 919 m._files = matchfiles |
759 m._fileset = set(m._files) | 920 m._fileset = set(m._files) |
760 origmatchfn = m.matchfn | 921 origmatchfn = m.matchfn |
922 | |
761 def matchfn(f): | 923 def matchfn(f): |
762 lfile = lfutil.splitstandin(f) | 924 lfile = lfutil.splitstandin(f) |
763 if lfile is not None: | 925 if lfile is not None: |
764 return (origmatchfn(lfile) and | 926 return origmatchfn(lfile) and (f in ctx or f in mctx) |
765 (f in ctx or f in mctx)) | |
766 return origmatchfn(f) | 927 return origmatchfn(f) |
928 | |
767 m.matchfn = matchfn | 929 m.matchfn = matchfn |
768 return m | 930 return m |
931 | |
769 with extensions.wrappedfunction(scmutil, 'match', overridematch): | 932 with extensions.wrappedfunction(scmutil, 'match', overridematch): |
770 orig(ui, repo, ctx, parents, *pats, **opts) | 933 orig(ui, repo, ctx, parents, *pats, **opts) |
771 | 934 |
772 newstandins = lfutil.getstandinsstate(repo) | 935 newstandins = lfutil.getstandinsstate(repo) |
773 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) | 936 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) |
774 # lfdirstate should be 'normallookup'-ed for updated files, | 937 # lfdirstate should be 'normallookup'-ed for updated files, |
775 # because reverting doesn't touch dirstate for 'normal' files | 938 # because reverting doesn't touch dirstate for 'normal' files |
776 # when target revision is explicitly specified: in such case, | 939 # when target revision is explicitly specified: in such case, |
777 # 'n' and valid timestamp in dirstate doesn't ensure 'clean' | 940 # 'n' and valid timestamp in dirstate doesn't ensure 'clean' |
778 # of target (standin) file. | 941 # of target (standin) file. |
779 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False, | 942 lfcommands.updatelfiles( |
780 normallookup=True) | 943 ui, repo, filelist, printmessage=False, normallookup=True |
944 ) | |
945 | |
781 | 946 |
782 # after pulling changesets, we need to take some extra care to get | 947 # after pulling changesets, we need to take some extra care to get |
783 # largefiles updated remotely | 948 # largefiles updated remotely |
784 @eh.wrapcommand('pull', | 949 @eh.wrapcommand( |
785 opts=[('', 'all-largefiles', None, | 950 'pull', |
786 _('download all pulled versions of largefiles (DEPRECATED)')), | 951 opts=[ |
787 ('', 'lfrev', [], | 952 ( |
788 _('download largefiles for these revisions'), _('REV'))]) | 953 '', |
954 'all-largefiles', | |
955 None, | |
956 _('download all pulled versions of largefiles (DEPRECATED)'), | |
957 ), | |
958 ( | |
959 '', | |
960 'lfrev', | |
961 [], | |
962 _('download largefiles for these revisions'), | |
963 _('REV'), | |
964 ), | |
965 ], | |
966 ) | |
789 def overridepull(orig, ui, repo, source=None, **opts): | 967 def overridepull(orig, ui, repo, source=None, **opts): |
790 revsprepull = len(repo) | 968 revsprepull = len(repo) |
791 if not source: | 969 if not source: |
792 source = 'default' | 970 source = 'default' |
793 repo.lfpullsource = source | 971 repo.lfpullsource = source |
796 lfrevs = opts.get(r'lfrev', []) | 974 lfrevs = opts.get(r'lfrev', []) |
797 if opts.get(r'all_largefiles'): | 975 if opts.get(r'all_largefiles'): |
798 lfrevs.append('pulled()') | 976 lfrevs.append('pulled()') |
799 if lfrevs and revspostpull > revsprepull: | 977 if lfrevs and revspostpull > revsprepull: |
800 numcached = 0 | 978 numcached = 0 |
801 repo.firstpulled = revsprepull # for pulled() revset expression | 979 repo.firstpulled = revsprepull # for pulled() revset expression |
802 try: | 980 try: |
803 for rev in scmutil.revrange(repo, lfrevs): | 981 for rev in scmutil.revrange(repo, lfrevs): |
804 ui.note(_('pulling largefiles for revision %d\n') % rev) | 982 ui.note(_('pulling largefiles for revision %d\n') % rev) |
805 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev) | 983 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev) |
806 numcached += len(cached) | 984 numcached += len(cached) |
807 finally: | 985 finally: |
808 del repo.firstpulled | 986 del repo.firstpulled |
809 ui.status(_("%d largefiles cached\n") % numcached) | 987 ui.status(_("%d largefiles cached\n") % numcached) |
810 return result | 988 return result |
811 | 989 |
812 @eh.wrapcommand('push', | 990 |
813 opts=[('', 'lfrev', [], | 991 @eh.wrapcommand( |
814 _('upload largefiles for these revisions'), _('REV'))]) | 992 'push', |
993 opts=[ | |
994 ('', 'lfrev', [], _('upload largefiles for these revisions'), _('REV')) | |
995 ], | |
996 ) | |
815 def overridepush(orig, ui, repo, *args, **kwargs): | 997 def overridepush(orig, ui, repo, *args, **kwargs): |
816 """Override push command and store --lfrev parameters in opargs""" | 998 """Override push command and store --lfrev parameters in opargs""" |
817 lfrevs = kwargs.pop(r'lfrev', None) | 999 lfrevs = kwargs.pop(r'lfrev', None) |
818 if lfrevs: | 1000 if lfrevs: |
819 opargs = kwargs.setdefault(r'opargs', {}) | 1001 opargs = kwargs.setdefault(r'opargs', {}) |
820 opargs['lfrevs'] = scmutil.revrange(repo, lfrevs) | 1002 opargs['lfrevs'] = scmutil.revrange(repo, lfrevs) |
821 return orig(ui, repo, *args, **kwargs) | 1003 return orig(ui, repo, *args, **kwargs) |
822 | 1004 |
1005 | |
823 @eh.wrapfunction(exchange, 'pushoperation') | 1006 @eh.wrapfunction(exchange, 'pushoperation') |
824 def exchangepushoperation(orig, *args, **kwargs): | 1007 def exchangepushoperation(orig, *args, **kwargs): |
825 """Override pushoperation constructor and store lfrevs parameter""" | 1008 """Override pushoperation constructor and store lfrevs parameter""" |
826 lfrevs = kwargs.pop(r'lfrevs', None) | 1009 lfrevs = kwargs.pop(r'lfrevs', None) |
827 pushop = orig(*args, **kwargs) | 1010 pushop = orig(*args, **kwargs) |
828 pushop.lfrevs = lfrevs | 1011 pushop.lfrevs = lfrevs |
829 return pushop | 1012 return pushop |
830 | 1013 |
1014 | |
831 @eh.revsetpredicate('pulled()') | 1015 @eh.revsetpredicate('pulled()') |
832 def pulledrevsetsymbol(repo, subset, x): | 1016 def pulledrevsetsymbol(repo, subset, x): |
833 """Changesets that just has been pulled. | 1017 """Changesets that just has been pulled. |
834 | 1018 |
835 Only available with largefiles from pull --lfrev expressions. | 1019 Only available with largefiles from pull --lfrev expressions. |
852 firstpulled = repo.firstpulled | 1036 firstpulled = repo.firstpulled |
853 except AttributeError: | 1037 except AttributeError: |
854 raise error.Abort(_("pulled() only available in --lfrev")) | 1038 raise error.Abort(_("pulled() only available in --lfrev")) |
855 return smartset.baseset([r for r in subset if r >= firstpulled]) | 1039 return smartset.baseset([r for r in subset if r >= firstpulled]) |
856 | 1040 |
857 @eh.wrapcommand('clone', | 1041 |
858 opts=[('', 'all-largefiles', None, | 1042 @eh.wrapcommand( |
859 _('download all versions of all largefiles'))]) | 1043 'clone', |
1044 opts=[ | |
1045 ( | |
1046 '', | |
1047 'all-largefiles', | |
1048 None, | |
1049 _('download all versions of all largefiles'), | |
1050 ) | |
1051 ], | |
1052 ) | |
860 def overrideclone(orig, ui, source, dest=None, **opts): | 1053 def overrideclone(orig, ui, source, dest=None, **opts): |
861 d = dest | 1054 d = dest |
862 if d is None: | 1055 if d is None: |
863 d = hg.defaultdest(source) | 1056 d = hg.defaultdest(source) |
864 if opts.get(r'all_largefiles') and not hg.islocal(d): | 1057 if opts.get(r'all_largefiles') and not hg.islocal(d): |
865 raise error.Abort(_( | 1058 raise error.Abort( |
866 '--all-largefiles is incompatible with non-local destination %s') % | 1059 _('--all-largefiles is incompatible with non-local destination %s') |
867 d) | 1060 % d |
1061 ) | |
868 | 1062 |
869 return orig(ui, source, dest, **opts) | 1063 return orig(ui, source, dest, **opts) |
1064 | |
870 | 1065 |
871 @eh.wrapfunction(hg, 'clone') | 1066 @eh.wrapfunction(hg, 'clone') |
872 def hgclone(orig, ui, opts, *args, **kwargs): | 1067 def hgclone(orig, ui, opts, *args, **kwargs): |
873 result = orig(ui, opts, *args, **kwargs) | 1068 result = orig(ui, opts, *args, **kwargs) |
874 | 1069 |
890 | 1085 |
891 if missing != 0: | 1086 if missing != 0: |
892 return None | 1087 return None |
893 | 1088 |
894 return result | 1089 return result |
1090 | |
895 | 1091 |
896 @eh.wrapcommand('rebase', extension='rebase') | 1092 @eh.wrapcommand('rebase', extension='rebase') |
897 def overriderebase(orig, ui, repo, **opts): | 1093 def overriderebase(orig, ui, repo, **opts): |
898 if not util.safehasattr(repo, '_largefilesenabled'): | 1094 if not util.safehasattr(repo, '_largefilesenabled'): |
899 return orig(ui, repo, **opts) | 1095 return orig(ui, repo, **opts) |
905 return orig(ui, repo, **opts) | 1101 return orig(ui, repo, **opts) |
906 finally: | 1102 finally: |
907 repo._lfstatuswriters.pop() | 1103 repo._lfstatuswriters.pop() |
908 repo._lfcommithooks.pop() | 1104 repo._lfcommithooks.pop() |
909 | 1105 |
1106 | |
910 @eh.wrapcommand('archive') | 1107 @eh.wrapcommand('archive') |
911 def overridearchivecmd(orig, ui, repo, dest, **opts): | 1108 def overridearchivecmd(orig, ui, repo, dest, **opts): |
912 repo.unfiltered().lfstatus = True | 1109 repo.unfiltered().lfstatus = True |
913 | 1110 |
914 try: | 1111 try: |
915 return orig(ui, repo.unfiltered(), dest, **opts) | 1112 return orig(ui, repo.unfiltered(), dest, **opts) |
916 finally: | 1113 finally: |
917 repo.unfiltered().lfstatus = False | 1114 repo.unfiltered().lfstatus = False |
918 | 1115 |
1116 | |
919 @eh.wrapfunction(webcommands, 'archive') | 1117 @eh.wrapfunction(webcommands, 'archive') |
920 def hgwebarchive(orig, web): | 1118 def hgwebarchive(orig, web): |
921 web.repo.lfstatus = True | 1119 web.repo.lfstatus = True |
922 | 1120 |
923 try: | 1121 try: |
924 return orig(web) | 1122 return orig(web) |
925 finally: | 1123 finally: |
926 web.repo.lfstatus = False | 1124 web.repo.lfstatus = False |
927 | 1125 |
1126 | |
928 @eh.wrapfunction(archival, 'archive') | 1127 @eh.wrapfunction(archival, 'archive') |
929 def overridearchive(orig, repo, dest, node, kind, decode=True, match=None, | 1128 def overridearchive( |
930 prefix='', mtime=None, subrepos=None): | 1129 orig, |
1130 repo, | |
1131 dest, | |
1132 node, | |
1133 kind, | |
1134 decode=True, | |
1135 match=None, | |
1136 prefix='', | |
1137 mtime=None, | |
1138 subrepos=None, | |
1139 ): | |
931 # For some reason setting repo.lfstatus in hgwebarchive only changes the | 1140 # For some reason setting repo.lfstatus in hgwebarchive only changes the |
932 # unfiltered repo's attr, so check that as well. | 1141 # unfiltered repo's attr, so check that as well. |
933 if not repo.lfstatus and not repo.unfiltered().lfstatus: | 1142 if not repo.lfstatus and not repo.unfiltered().lfstatus: |
934 return orig(repo, dest, node, kind, decode, match, prefix, mtime, | 1143 return orig( |
935 subrepos) | 1144 repo, dest, node, kind, decode, match, prefix, mtime, subrepos |
1145 ) | |
936 | 1146 |
937 # No need to lock because we are only reading history and | 1147 # No need to lock because we are only reading history and |
938 # largefile caches, neither of which are modified. | 1148 # largefile caches, neither of which are modified. |
939 if node is not None: | 1149 if node is not None: |
940 lfcommands.cachelfiles(repo.ui, repo, node) | 1150 lfcommands.cachelfiles(repo.ui, repo, node) |
944 | 1154 |
945 ctx = repo[node] | 1155 ctx = repo[node] |
946 | 1156 |
947 if kind == 'files': | 1157 if kind == 'files': |
948 if prefix: | 1158 if prefix: |
949 raise error.Abort( | 1159 raise error.Abort(_('cannot give prefix when archiving to files')) |
950 _('cannot give prefix when archiving to files')) | |
951 else: | 1160 else: |
952 prefix = archival.tidyprefix(dest, kind, prefix) | 1161 prefix = archival.tidyprefix(dest, kind, prefix) |
953 | 1162 |
954 def write(name, mode, islink, getdata): | 1163 def write(name, mode, islink, getdata): |
955 if match and not match(name): | 1164 if match and not match(name): |
960 archiver.addfile(prefix + name, mode, islink, data) | 1169 archiver.addfile(prefix + name, mode, islink, data) |
961 | 1170 |
962 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) | 1171 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) |
963 | 1172 |
964 if repo.ui.configbool("ui", "archivemeta"): | 1173 if repo.ui.configbool("ui", "archivemeta"): |
965 write('.hg_archival.txt', 0o644, False, | 1174 write( |
966 lambda: archival.buildmetadata(ctx)) | 1175 '.hg_archival.txt', |
1176 0o644, | |
1177 False, | |
1178 lambda: archival.buildmetadata(ctx), | |
1179 ) | |
967 | 1180 |
968 for f in ctx: | 1181 for f in ctx: |
969 ff = ctx.flags(f) | 1182 ff = ctx.flags(f) |
970 getdata = ctx[f].data | 1183 getdata = ctx[f].data |
971 lfile = lfutil.splitstandin(f) | 1184 lfile = lfutil.splitstandin(f) |
973 if node is not None: | 1186 if node is not None: |
974 path = lfutil.findfile(repo, getdata().strip()) | 1187 path = lfutil.findfile(repo, getdata().strip()) |
975 | 1188 |
976 if path is None: | 1189 if path is None: |
977 raise error.Abort( | 1190 raise error.Abort( |
978 _('largefile %s not found in repo store or system cache') | 1191 _( |
979 % lfile) | 1192 'largefile %s not found in repo store or system cache' |
1193 ) | |
1194 % lfile | |
1195 ) | |
980 else: | 1196 else: |
981 path = lfile | 1197 path = lfile |
982 | 1198 |
983 f = lfile | 1199 f = lfile |
984 | 1200 |
992 subprefix = prefix + subpath + '/' | 1208 subprefix = prefix + subpath + '/' |
993 sub._repo.lfstatus = True | 1209 sub._repo.lfstatus = True |
994 sub.archive(archiver, subprefix, submatch) | 1210 sub.archive(archiver, subprefix, submatch) |
995 | 1211 |
996 archiver.done() | 1212 archiver.done() |
1213 | |
997 | 1214 |
998 @eh.wrapfunction(subrepo.hgsubrepo, 'archive') | 1215 @eh.wrapfunction(subrepo.hgsubrepo, 'archive') |
999 def hgsubrepoarchive(orig, repo, archiver, prefix, match=None, decode=True): | 1216 def hgsubrepoarchive(orig, repo, archiver, prefix, match=None, decode=True): |
1000 lfenabled = util.safehasattr(repo._repo, '_largefilesenabled') | 1217 lfenabled = util.safehasattr(repo._repo, '_largefilesenabled') |
1001 if not lfenabled or not repo._repo.lfstatus: | 1218 if not lfenabled or not repo._repo.lfstatus: |
1027 if ctx.node() is not None: | 1244 if ctx.node() is not None: |
1028 path = lfutil.findfile(repo._repo, getdata().strip()) | 1245 path = lfutil.findfile(repo._repo, getdata().strip()) |
1029 | 1246 |
1030 if path is None: | 1247 if path is None: |
1031 raise error.Abort( | 1248 raise error.Abort( |
1032 _('largefile %s not found in repo store or system cache') | 1249 _( |
1033 % lfile) | 1250 'largefile %s not found in repo store or system cache' |
1251 ) | |
1252 % lfile | |
1253 ) | |
1034 else: | 1254 else: |
1035 path = lfile | 1255 path = lfile |
1036 | 1256 |
1037 f = lfile | 1257 f = lfile |
1038 | 1258 |
1044 sub = ctx.workingsub(subpath) | 1264 sub = ctx.workingsub(subpath) |
1045 submatch = matchmod.subdirmatcher(subpath, match) | 1265 submatch = matchmod.subdirmatcher(subpath, match) |
1046 subprefix = prefix + subpath + '/' | 1266 subprefix = prefix + subpath + '/' |
1047 sub._repo.lfstatus = True | 1267 sub._repo.lfstatus = True |
1048 sub.archive(archiver, subprefix, submatch, decode) | 1268 sub.archive(archiver, subprefix, submatch, decode) |
1269 | |
1049 | 1270 |
1050 # If a largefile is modified, the change is not reflected in its | 1271 # If a largefile is modified, the change is not reflected in its |
1051 # standin until a commit. cmdutil.bailifchanged() raises an exception | 1272 # standin until a commit. cmdutil.bailifchanged() raises an exception |
1052 # if the repo has uncommitted changes. Wrap it to also check if | 1273 # if the repo has uncommitted changes. Wrap it to also check if |
1053 # largefiles were changed. This is used by bisect, backout and fetch. | 1274 # largefiles were changed. This is used by bisect, backout and fetch. |
1058 s = repo.status() | 1279 s = repo.status() |
1059 repo.lfstatus = False | 1280 repo.lfstatus = False |
1060 if s.modified or s.added or s.removed or s.deleted: | 1281 if s.modified or s.added or s.removed or s.deleted: |
1061 raise error.Abort(_('uncommitted changes')) | 1282 raise error.Abort(_('uncommitted changes')) |
1062 | 1283 |
1284 | |
1063 @eh.wrapfunction(cmdutil, 'postcommitstatus') | 1285 @eh.wrapfunction(cmdutil, 'postcommitstatus') |
1064 def postcommitstatus(orig, repo, *args, **kwargs): | 1286 def postcommitstatus(orig, repo, *args, **kwargs): |
1065 repo.lfstatus = True | 1287 repo.lfstatus = True |
1066 try: | 1288 try: |
1067 return orig(repo, *args, **kwargs) | 1289 return orig(repo, *args, **kwargs) |
1068 finally: | 1290 finally: |
1069 repo.lfstatus = False | 1291 repo.lfstatus = False |
1070 | 1292 |
1293 | |
1071 @eh.wrapfunction(cmdutil, 'forget') | 1294 @eh.wrapfunction(cmdutil, 'forget') |
1072 def cmdutilforget(orig, ui, repo, match, prefix, uipathfn, explicitonly, dryrun, | 1295 def cmdutilforget( |
1073 interactive): | 1296 orig, ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive |
1297 ): | |
1074 normalmatcher = composenormalfilematcher(match, repo[None].manifest()) | 1298 normalmatcher = composenormalfilematcher(match, repo[None].manifest()) |
1075 bad, forgot = orig(ui, repo, normalmatcher, prefix, uipathfn, explicitonly, | 1299 bad, forgot = orig( |
1076 dryrun, interactive) | 1300 ui, |
1301 repo, | |
1302 normalmatcher, | |
1303 prefix, | |
1304 uipathfn, | |
1305 explicitonly, | |
1306 dryrun, | |
1307 interactive, | |
1308 ) | |
1077 m = composelargefilematcher(match, repo[None].manifest()) | 1309 m = composelargefilematcher(match, repo[None].manifest()) |
1078 | 1310 |
1079 try: | 1311 try: |
1080 repo.lfstatus = True | 1312 repo.lfstatus = True |
1081 s = repo.status(match=m, clean=True) | 1313 s = repo.status(match=m, clean=True) |
1086 forget = [f for f in forget if lfutil.standin(f) in manifest] | 1318 forget = [f for f in forget if lfutil.standin(f) in manifest] |
1087 | 1319 |
1088 for f in forget: | 1320 for f in forget: |
1089 fstandin = lfutil.standin(f) | 1321 fstandin = lfutil.standin(f) |
1090 if fstandin not in repo.dirstate and not repo.wvfs.isdir(fstandin): | 1322 if fstandin not in repo.dirstate and not repo.wvfs.isdir(fstandin): |
1091 ui.warn(_('not removing %s: file is already untracked\n') | 1323 ui.warn( |
1092 % uipathfn(f)) | 1324 _('not removing %s: file is already untracked\n') % uipathfn(f) |
1325 ) | |
1093 bad.append(f) | 1326 bad.append(f) |
1094 | 1327 |
1095 for f in forget: | 1328 for f in forget: |
1096 if ui.verbose or not m.exact(f): | 1329 if ui.verbose or not m.exact(f): |
1097 ui.status(_('removing %s\n') % uipathfn(f)) | 1330 ui.status(_('removing %s\n') % uipathfn(f)) |
1113 | 1346 |
1114 bad.extend(f for f in rejected if f in m.files()) | 1347 bad.extend(f for f in rejected if f in m.files()) |
1115 forgot.extend(f for f in forget if f not in rejected) | 1348 forgot.extend(f for f in forget if f not in rejected) |
1116 return bad, forgot | 1349 return bad, forgot |
1117 | 1350 |
1351 | |
1118 def _getoutgoings(repo, other, missing, addfunc): | 1352 def _getoutgoings(repo, other, missing, addfunc): |
1119 """get pairs of filename and largefile hash in outgoing revisions | 1353 """get pairs of filename and largefile hash in outgoing revisions |
1120 in 'missing'. | 1354 in 'missing'. |
1121 | 1355 |
1122 largefiles already existing on 'other' repository are ignored. | 1356 largefiles already existing on 'other' repository are ignored. |
1124 'addfunc' is invoked with each unique pairs of filename and | 1358 'addfunc' is invoked with each unique pairs of filename and |
1125 largefile hash value. | 1359 largefile hash value. |
1126 """ | 1360 """ |
1127 knowns = set() | 1361 knowns = set() |
1128 lfhashes = set() | 1362 lfhashes = set() |
1363 | |
1129 def dedup(fn, lfhash): | 1364 def dedup(fn, lfhash): |
1130 k = (fn, lfhash) | 1365 k = (fn, lfhash) |
1131 if k not in knowns: | 1366 if k not in knowns: |
1132 knowns.add(k) | 1367 knowns.add(k) |
1133 lfhashes.add(lfhash) | 1368 lfhashes.add(lfhash) |
1369 | |
1134 lfutil.getlfilestoupload(repo, missing, dedup) | 1370 lfutil.getlfilestoupload(repo, missing, dedup) |
1135 if lfhashes: | 1371 if lfhashes: |
1136 lfexists = storefactory.openstore(repo, other).exists(lfhashes) | 1372 lfexists = storefactory.openstore(repo, other).exists(lfhashes) |
1137 for fn, lfhash in knowns: | 1373 for fn, lfhash in knowns: |
1138 if not lfexists[lfhash]: # lfhash doesn't exist on "other" | 1374 if not lfexists[lfhash]: # lfhash doesn't exist on "other" |
1139 addfunc(fn, lfhash) | 1375 addfunc(fn, lfhash) |
1376 | |
1140 | 1377 |
1141 def outgoinghook(ui, repo, other, opts, missing): | 1378 def outgoinghook(ui, repo, other, opts, missing): |
1142 if opts.pop('large', None): | 1379 if opts.pop('large', None): |
1143 lfhashes = set() | 1380 lfhashes = set() |
1144 if ui.debugflag: | 1381 if ui.debugflag: |
1145 toupload = {} | 1382 toupload = {} |
1383 | |
1146 def addfunc(fn, lfhash): | 1384 def addfunc(fn, lfhash): |
1147 if fn not in toupload: | 1385 if fn not in toupload: |
1148 toupload[fn] = [] | 1386 toupload[fn] = [] |
1149 toupload[fn].append(lfhash) | 1387 toupload[fn].append(lfhash) |
1150 lfhashes.add(lfhash) | 1388 lfhashes.add(lfhash) |
1389 | |
1151 def showhashes(fn): | 1390 def showhashes(fn): |
1152 for lfhash in sorted(toupload[fn]): | 1391 for lfhash in sorted(toupload[fn]): |
1153 ui.debug(' %s\n' % (lfhash)) | 1392 ui.debug(' %s\n' % lfhash) |
1393 | |
1154 else: | 1394 else: |
1155 toupload = set() | 1395 toupload = set() |
1396 | |
1156 def addfunc(fn, lfhash): | 1397 def addfunc(fn, lfhash): |
1157 toupload.add(fn) | 1398 toupload.add(fn) |
1158 lfhashes.add(lfhash) | 1399 lfhashes.add(lfhash) |
1400 | |
1159 def showhashes(fn): | 1401 def showhashes(fn): |
1160 pass | 1402 pass |
1403 | |
1161 _getoutgoings(repo, other, missing, addfunc) | 1404 _getoutgoings(repo, other, missing, addfunc) |
1162 | 1405 |
1163 if not toupload: | 1406 if not toupload: |
1164 ui.status(_('largefiles: no files to upload\n')) | 1407 ui.status(_('largefiles: no files to upload\n')) |
1165 else: | 1408 else: |
1166 ui.status(_('largefiles to upload (%d entities):\n') | 1409 ui.status( |
1167 % (len(lfhashes))) | 1410 _('largefiles to upload (%d entities):\n') % (len(lfhashes)) |
1411 ) | |
1168 for file in sorted(toupload): | 1412 for file in sorted(toupload): |
1169 ui.status(lfutil.splitstandin(file) + '\n') | 1413 ui.status(lfutil.splitstandin(file) + '\n') |
1170 showhashes(file) | 1414 showhashes(file) |
1171 ui.status('\n') | 1415 ui.status('\n') |
1172 | 1416 |
1173 @eh.wrapcommand('outgoing', | 1417 |
1174 opts=[('', 'large', None, _('display outgoing largefiles'))]) | 1418 @eh.wrapcommand( |
1419 'outgoing', opts=[('', 'large', None, _('display outgoing largefiles'))] | |
1420 ) | |
1175 def _outgoingcmd(orig, *args, **kwargs): | 1421 def _outgoingcmd(orig, *args, **kwargs): |
1176 # Nothing to do here other than add the extra help option- the hook above | 1422 # Nothing to do here other than add the extra help option- the hook above |
1177 # processes it. | 1423 # processes it. |
1178 return orig(*args, **kwargs) | 1424 return orig(*args, **kwargs) |
1179 | 1425 |
1426 | |
1180 def summaryremotehook(ui, repo, opts, changes): | 1427 def summaryremotehook(ui, repo, opts, changes): |
1181 largeopt = opts.get('large', False) | 1428 largeopt = opts.get('large', False) |
1182 if changes is None: | 1429 if changes is None: |
1183 if largeopt: | 1430 if largeopt: |
1184 return (False, True) # only outgoing check is needed | 1431 return (False, True) # only outgoing check is needed |
1185 else: | 1432 else: |
1186 return (False, False) | 1433 return (False, False) |
1187 elif largeopt: | 1434 elif largeopt: |
1188 url, branch, peer, outgoing = changes[1] | 1435 url, branch, peer, outgoing = changes[1] |
1189 if peer is None: | 1436 if peer is None: |
1191 ui.status(_('largefiles: (no remote repo)\n')) | 1438 ui.status(_('largefiles: (no remote repo)\n')) |
1192 return | 1439 return |
1193 | 1440 |
1194 toupload = set() | 1441 toupload = set() |
1195 lfhashes = set() | 1442 lfhashes = set() |
1443 | |
1196 def addfunc(fn, lfhash): | 1444 def addfunc(fn, lfhash): |
1197 toupload.add(fn) | 1445 toupload.add(fn) |
1198 lfhashes.add(lfhash) | 1446 lfhashes.add(lfhash) |
1447 | |
1199 _getoutgoings(repo, peer, outgoing.missing, addfunc) | 1448 _getoutgoings(repo, peer, outgoing.missing, addfunc) |
1200 | 1449 |
1201 if not toupload: | 1450 if not toupload: |
1202 # i18n: column positioning for "hg summary" | 1451 # i18n: column positioning for "hg summary" |
1203 ui.status(_('largefiles: (no files to upload)\n')) | 1452 ui.status(_('largefiles: (no files to upload)\n')) |
1204 else: | 1453 else: |
1205 # i18n: column positioning for "hg summary" | 1454 # i18n: column positioning for "hg summary" |
1206 ui.status(_('largefiles: %d entities for %d files to upload\n') | 1455 ui.status( |
1207 % (len(lfhashes), len(toupload))) | 1456 _('largefiles: %d entities for %d files to upload\n') |
1208 | 1457 % (len(lfhashes), len(toupload)) |
1209 @eh.wrapcommand('summary', | 1458 ) |
1210 opts=[('', 'large', None, _('display outgoing largefiles'))]) | 1459 |
1460 | |
1461 @eh.wrapcommand( | |
1462 'summary', opts=[('', 'large', None, _('display outgoing largefiles'))] | |
1463 ) | |
1211 def overridesummary(orig, ui, repo, *pats, **opts): | 1464 def overridesummary(orig, ui, repo, *pats, **opts): |
1212 try: | 1465 try: |
1213 repo.lfstatus = True | 1466 repo.lfstatus = True |
1214 orig(ui, repo, *pats, **opts) | 1467 orig(ui, repo, *pats, **opts) |
1215 finally: | 1468 finally: |
1216 repo.lfstatus = False | 1469 repo.lfstatus = False |
1470 | |
1217 | 1471 |
1218 @eh.wrapfunction(scmutil, 'addremove') | 1472 @eh.wrapfunction(scmutil, 'addremove') |
1219 def scmutiladdremove(orig, repo, matcher, prefix, uipathfn, opts=None): | 1473 def scmutiladdremove(orig, repo, matcher, prefix, uipathfn, opts=None): |
1220 if opts is None: | 1474 if opts is None: |
1221 opts = {} | 1475 opts = {} |
1222 if not lfutil.islfilesrepo(repo): | 1476 if not lfutil.islfilesrepo(repo): |
1223 return orig(repo, matcher, prefix, uipathfn, opts) | 1477 return orig(repo, matcher, prefix, uipathfn, opts) |
1224 # Get the list of missing largefiles so we can remove them | 1478 # Get the list of missing largefiles so we can remove them |
1225 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | 1479 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
1226 unsure, s = lfdirstate.status(matchmod.always(), subrepos=[], | 1480 unsure, s = lfdirstate.status( |
1227 ignored=False, clean=False, unknown=False) | 1481 matchmod.always(), |
1482 subrepos=[], | |
1483 ignored=False, | |
1484 clean=False, | |
1485 unknown=False, | |
1486 ) | |
1228 | 1487 |
1229 # Call into the normal remove code, but the removing of the standin, we want | 1488 # Call into the normal remove code, but the removing of the standin, we want |
1230 # to have handled by original addremove. Monkey patching here makes sure | 1489 # to have handled by original addremove. Monkey patching here makes sure |
1231 # we don't remove the standin in the largefiles code, preventing a very | 1490 # we don't remove the standin in the largefiles code, preventing a very |
1232 # confused state later. | 1491 # confused state later. |
1238 # or not the file name is printed, and how. Simply limit the original | 1497 # or not the file name is printed, and how. Simply limit the original |
1239 # matches to those in the deleted status list. | 1498 # matches to those in the deleted status list. |
1240 matchfn = m.matchfn | 1499 matchfn = m.matchfn |
1241 m.matchfn = lambda f: f in s.deleted and matchfn(f) | 1500 m.matchfn = lambda f: f in s.deleted and matchfn(f) |
1242 | 1501 |
1243 removelargefiles(repo.ui, repo, True, m, uipathfn, opts.get('dry_run'), | 1502 removelargefiles( |
1244 **pycompat.strkwargs(opts)) | 1503 repo.ui, |
1504 repo, | |
1505 True, | |
1506 m, | |
1507 uipathfn, | |
1508 opts.get('dry_run'), | |
1509 **pycompat.strkwargs(opts) | |
1510 ) | |
1245 # Call into the normal add code, and any files that *should* be added as | 1511 # Call into the normal add code, and any files that *should* be added as |
1246 # largefiles will be | 1512 # largefiles will be |
1247 added, bad = addlargefiles(repo.ui, repo, True, matcher, uipathfn, | 1513 added, bad = addlargefiles( |
1248 **pycompat.strkwargs(opts)) | 1514 repo.ui, repo, True, matcher, uipathfn, **pycompat.strkwargs(opts) |
1515 ) | |
1249 # Now that we've handled largefiles, hand off to the original addremove | 1516 # Now that we've handled largefiles, hand off to the original addremove |
1250 # function to take care of the rest. Make sure it doesn't do anything with | 1517 # function to take care of the rest. Make sure it doesn't do anything with |
1251 # largefiles by passing a matcher that will ignore them. | 1518 # largefiles by passing a matcher that will ignore them. |
1252 matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) | 1519 matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) |
1253 return orig(repo, matcher, prefix, uipathfn, opts) | 1520 return orig(repo, matcher, prefix, uipathfn, opts) |
1521 | |
1254 | 1522 |
1255 # Calling purge with --all will cause the largefiles to be deleted. | 1523 # Calling purge with --all will cause the largefiles to be deleted. |
1256 # Override repo.status to prevent this from happening. | 1524 # Override repo.status to prevent this from happening. |
1257 @eh.wrapcommand('purge', extension='purge') | 1525 @eh.wrapcommand('purge', extension='purge') |
1258 def overridepurge(orig, ui, repo, *dirs, **opts): | 1526 def overridepurge(orig, ui, repo, *dirs, **opts): |
1265 # | 1533 # |
1266 # As a work around we use an unfiltered repo here. We should do something | 1534 # As a work around we use an unfiltered repo here. We should do something |
1267 # cleaner instead. | 1535 # cleaner instead. |
1268 repo = repo.unfiltered() | 1536 repo = repo.unfiltered() |
1269 oldstatus = repo.status | 1537 oldstatus = repo.status |
1270 def overridestatus(node1='.', node2=None, match=None, ignored=False, | 1538 |
1271 clean=False, unknown=False, listsubrepos=False): | 1539 def overridestatus( |
1272 r = oldstatus(node1, node2, match, ignored, clean, unknown, | 1540 node1='.', |
1273 listsubrepos) | 1541 node2=None, |
1542 match=None, | |
1543 ignored=False, | |
1544 clean=False, | |
1545 unknown=False, | |
1546 listsubrepos=False, | |
1547 ): | |
1548 r = oldstatus( | |
1549 node1, node2, match, ignored, clean, unknown, listsubrepos | |
1550 ) | |
1274 lfdirstate = lfutil.openlfdirstate(ui, repo) | 1551 lfdirstate = lfutil.openlfdirstate(ui, repo) |
1275 unknown = [f for f in r.unknown if lfdirstate[f] == '?'] | 1552 unknown = [f for f in r.unknown if lfdirstate[f] == '?'] |
1276 ignored = [f for f in r.ignored if lfdirstate[f] == '?'] | 1553 ignored = [f for f in r.ignored if lfdirstate[f] == '?'] |
1277 return scmutil.status(r.modified, r.added, r.removed, r.deleted, | 1554 return scmutil.status( |
1278 unknown, ignored, r.clean) | 1555 r.modified, r.added, r.removed, r.deleted, unknown, ignored, r.clean |
1556 ) | |
1557 | |
1279 repo.status = overridestatus | 1558 repo.status = overridestatus |
1280 orig(ui, repo, *dirs, **opts) | 1559 orig(ui, repo, *dirs, **opts) |
1281 repo.status = oldstatus | 1560 repo.status = oldstatus |
1561 | |
1282 | 1562 |
1283 @eh.wrapcommand('rollback') | 1563 @eh.wrapcommand('rollback') |
1284 def overriderollback(orig, ui, repo, **opts): | 1564 def overriderollback(orig, ui, repo, **opts): |
1285 with repo.wlock(): | 1565 with repo.wlock(): |
1286 before = repo.dirstate.parents() | 1566 before = repo.dirstate.parents() |
1287 orphans = set(f for f in repo.dirstate | 1567 orphans = set( |
1288 if lfutil.isstandin(f) and repo.dirstate[f] != 'r') | 1568 f |
1569 for f in repo.dirstate | |
1570 if lfutil.isstandin(f) and repo.dirstate[f] != 'r' | |
1571 ) | |
1289 result = orig(ui, repo, **opts) | 1572 result = orig(ui, repo, **opts) |
1290 after = repo.dirstate.parents() | 1573 after = repo.dirstate.parents() |
1291 if before == after: | 1574 if before == after: |
1292 return result # no need to restore standins | 1575 return result # no need to restore standins |
1293 | 1576 |
1294 pctx = repo['.'] | 1577 pctx = repo['.'] |
1295 for f in repo.dirstate: | 1578 for f in repo.dirstate: |
1296 if lfutil.isstandin(f): | 1579 if lfutil.isstandin(f): |
1297 orphans.discard(f) | 1580 orphans.discard(f) |
1316 for lfile in orphans: | 1599 for lfile in orphans: |
1317 lfdirstate.drop(lfile) | 1600 lfdirstate.drop(lfile) |
1318 lfdirstate.write() | 1601 lfdirstate.write() |
1319 return result | 1602 return result |
1320 | 1603 |
1604 | |
1321 @eh.wrapcommand('transplant', extension='transplant') | 1605 @eh.wrapcommand('transplant', extension='transplant') |
1322 def overridetransplant(orig, ui, repo, *revs, **opts): | 1606 def overridetransplant(orig, ui, repo, *revs, **opts): |
1323 resuming = opts.get(r'continue') | 1607 resuming = opts.get(r'continue') |
1324 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) | 1608 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) |
1325 repo._lfstatuswriters.append(lambda *msg, **opts: None) | 1609 repo._lfstatuswriters.append(lambda *msg, **opts: None) |
1328 finally: | 1612 finally: |
1329 repo._lfstatuswriters.pop() | 1613 repo._lfstatuswriters.pop() |
1330 repo._lfcommithooks.pop() | 1614 repo._lfcommithooks.pop() |
1331 return result | 1615 return result |
1332 | 1616 |
1617 | |
1333 @eh.wrapcommand('cat') | 1618 @eh.wrapcommand('cat') |
1334 def overridecat(orig, ui, repo, file1, *pats, **opts): | 1619 def overridecat(orig, ui, repo, file1, *pats, **opts): |
1335 opts = pycompat.byteskwargs(opts) | 1620 opts = pycompat.byteskwargs(opts) |
1336 ctx = scmutil.revsingle(repo, opts.get('rev')) | 1621 ctx = scmutil.revsingle(repo, opts.get('rev')) |
1337 err = 1 | 1622 err = 1 |
1338 notbad = set() | 1623 notbad = set() |
1339 m = scmutil.match(ctx, (file1,) + pats, opts) | 1624 m = scmutil.match(ctx, (file1,) + pats, opts) |
1340 origmatchfn = m.matchfn | 1625 origmatchfn = m.matchfn |
1626 | |
1341 def lfmatchfn(f): | 1627 def lfmatchfn(f): |
1342 if origmatchfn(f): | 1628 if origmatchfn(f): |
1343 return True | 1629 return True |
1344 lf = lfutil.splitstandin(f) | 1630 lf = lfutil.splitstandin(f) |
1345 if lf is None: | 1631 if lf is None: |
1346 return False | 1632 return False |
1347 notbad.add(lf) | 1633 notbad.add(lf) |
1348 return origmatchfn(lf) | 1634 return origmatchfn(lf) |
1635 | |
1349 m.matchfn = lfmatchfn | 1636 m.matchfn = lfmatchfn |
1350 origbadfn = m.bad | 1637 origbadfn = m.bad |
1638 | |
1351 def lfbadfn(f, msg): | 1639 def lfbadfn(f, msg): |
1352 if not f in notbad: | 1640 if not f in notbad: |
1353 origbadfn(f, msg) | 1641 origbadfn(f, msg) |
1642 | |
1354 m.bad = lfbadfn | 1643 m.bad = lfbadfn |
1355 | 1644 |
1356 origvisitdirfn = m.visitdir | 1645 origvisitdirfn = m.visitdir |
1646 | |
1357 def lfvisitdirfn(dir): | 1647 def lfvisitdirfn(dir): |
1358 if dir == lfutil.shortname: | 1648 if dir == lfutil.shortname: |
1359 return True | 1649 return True |
1360 ret = origvisitdirfn(dir) | 1650 ret = origvisitdirfn(dir) |
1361 if ret: | 1651 if ret: |
1362 return ret | 1652 return ret |
1363 lf = lfutil.splitstandin(dir) | 1653 lf = lfutil.splitstandin(dir) |
1364 if lf is None: | 1654 if lf is None: |
1365 return False | 1655 return False |
1366 return origvisitdirfn(lf) | 1656 return origvisitdirfn(lf) |
1657 | |
1367 m.visitdir = lfvisitdirfn | 1658 m.visitdir = lfvisitdirfn |
1368 | 1659 |
1369 for f in ctx.walk(m): | 1660 for f in ctx.walk(m): |
1370 with cmdutil.makefileobj(ctx, opts.get('output'), pathname=f) as fp: | 1661 with cmdutil.makefileobj(ctx, opts.get('output'), pathname=f) as fp: |
1371 lf = lfutil.splitstandin(f) | 1662 lf = lfutil.splitstandin(f) |
1380 if not lfutil.inusercache(repo.ui, hash): | 1671 if not lfutil.inusercache(repo.ui, hash): |
1381 store = storefactory.openstore(repo) | 1672 store = storefactory.openstore(repo) |
1382 success, missing = store.get([(lf, hash)]) | 1673 success, missing = store.get([(lf, hash)]) |
1383 if len(success) != 1: | 1674 if len(success) != 1: |
1384 raise error.Abort( | 1675 raise error.Abort( |
1385 _('largefile %s is not in cache and could not be ' | 1676 _( |
1386 'downloaded') % lf) | 1677 'largefile %s is not in cache and could not be ' |
1678 'downloaded' | |
1679 ) | |
1680 % lf | |
1681 ) | |
1387 path = lfutil.usercachepath(repo.ui, hash) | 1682 path = lfutil.usercachepath(repo.ui, hash) |
1388 with open(path, "rb") as fpin: | 1683 with open(path, "rb") as fpin: |
1389 for chunk in util.filechunkiter(fpin): | 1684 for chunk in util.filechunkiter(fpin): |
1390 fp.write(chunk) | 1685 fp.write(chunk) |
1391 err = 0 | 1686 err = 0 |
1392 return err | 1687 return err |
1393 | 1688 |
1689 | |
1394 @eh.wrapfunction(merge, 'update') | 1690 @eh.wrapfunction(merge, 'update') |
1395 def mergeupdate(orig, repo, node, branchmerge, force, | 1691 def mergeupdate(orig, repo, node, branchmerge, force, *args, **kwargs): |
1396 *args, **kwargs): | |
1397 matcher = kwargs.get(r'matcher', None) | 1692 matcher = kwargs.get(r'matcher', None) |
1398 # note if this is a partial update | 1693 # note if this is a partial update |
1399 partial = matcher and not matcher.always() | 1694 partial = matcher and not matcher.always() |
1400 with repo.wlock(): | 1695 with repo.wlock(): |
1401 # branch | | | | 1696 # branch | | | |
1412 # | 1707 # |
1413 # (*) don't care | 1708 # (*) don't care |
1414 # (*1) deprecated, but used internally (e.g: "rebase --collapse") | 1709 # (*1) deprecated, but used internally (e.g: "rebase --collapse") |
1415 | 1710 |
1416 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | 1711 lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
1417 unsure, s = lfdirstate.status(matchmod.always(), subrepos=[], | 1712 unsure, s = lfdirstate.status( |
1418 ignored=False, clean=True, unknown=False) | 1713 matchmod.always(), |
1714 subrepos=[], | |
1715 ignored=False, | |
1716 clean=True, | |
1717 unknown=False, | |
1718 ) | |
1419 oldclean = set(s.clean) | 1719 oldclean = set(s.clean) |
1420 pctx = repo['.'] | 1720 pctx = repo['.'] |
1421 dctx = repo[node] | 1721 dctx = repo[node] |
1422 for lfile in unsure + s.modified: | 1722 for lfile in unsure + s.modified: |
1423 lfileabs = repo.wvfs.join(lfile) | 1723 lfileabs = repo.wvfs.join(lfile) |
1424 if not repo.wvfs.exists(lfileabs): | 1724 if not repo.wvfs.exists(lfileabs): |
1425 continue | 1725 continue |
1426 lfhash = lfutil.hashfile(lfileabs) | 1726 lfhash = lfutil.hashfile(lfileabs) |
1427 standin = lfutil.standin(lfile) | 1727 standin = lfutil.standin(lfile) |
1428 lfutil.writestandin(repo, standin, lfhash, | 1728 lfutil.writestandin( |
1429 lfutil.getexecutable(lfileabs)) | 1729 repo, standin, lfhash, lfutil.getexecutable(lfileabs) |
1430 if (standin in pctx and | 1730 ) |
1431 lfhash == lfutil.readasstandin(pctx[standin])): | 1731 if standin in pctx and lfhash == lfutil.readasstandin( |
1732 pctx[standin] | |
1733 ): | |
1432 oldclean.add(lfile) | 1734 oldclean.add(lfile) |
1433 for lfile in s.added: | 1735 for lfile in s.added: |
1434 fstandin = lfutil.standin(lfile) | 1736 fstandin = lfutil.standin(lfile) |
1435 if fstandin not in dctx: | 1737 if fstandin not in dctx: |
1436 # in this case, content of standin file is meaningless | 1738 # in this case, content of standin file is meaningless |
1460 lfdirstate.write() | 1762 lfdirstate.write() |
1461 | 1763 |
1462 if branchmerge or force or partial: | 1764 if branchmerge or force or partial: |
1463 filelist.extend(s.deleted + s.removed) | 1765 filelist.extend(s.deleted + s.removed) |
1464 | 1766 |
1465 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, | 1767 lfcommands.updatelfiles( |
1466 normallookup=partial) | 1768 repo.ui, repo, filelist=filelist, normallookup=partial |
1769 ) | |
1467 | 1770 |
1468 return result | 1771 return result |
1772 | |
1469 | 1773 |
1470 @eh.wrapfunction(scmutil, 'marktouched') | 1774 @eh.wrapfunction(scmutil, 'marktouched') |
1471 def scmutilmarktouched(orig, repo, files, *args, **kwargs): | 1775 def scmutilmarktouched(orig, repo, files, *args, **kwargs): |
1472 result = orig(repo, files, *args, **kwargs) | 1776 result = orig(repo, files, *args, **kwargs) |
1473 | 1777 |
1475 for f in files: | 1779 for f in files: |
1476 lf = lfutil.splitstandin(f) | 1780 lf = lfutil.splitstandin(f) |
1477 if lf is not None: | 1781 if lf is not None: |
1478 filelist.append(lf) | 1782 filelist.append(lf) |
1479 if filelist: | 1783 if filelist: |
1480 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, | 1784 lfcommands.updatelfiles( |
1481 printmessage=False, normallookup=True) | 1785 repo.ui, |
1786 repo, | |
1787 filelist=filelist, | |
1788 printmessage=False, | |
1789 normallookup=True, | |
1790 ) | |
1482 | 1791 |
1483 return result | 1792 return result |
1793 | |
1484 | 1794 |
1485 @eh.wrapfunction(upgrade, 'preservedrequirements') | 1795 @eh.wrapfunction(upgrade, 'preservedrequirements') |
1486 @eh.wrapfunction(upgrade, 'supporteddestrequirements') | 1796 @eh.wrapfunction(upgrade, 'supporteddestrequirements') |
1487 def upgraderequirements(orig, repo): | 1797 def upgraderequirements(orig, repo): |
1488 reqs = orig(repo) | 1798 reqs = orig(repo) |
1489 if 'largefiles' in repo.requirements: | 1799 if 'largefiles' in repo.requirements: |
1490 reqs.add('largefiles') | 1800 reqs.add('largefiles') |
1491 return reqs | 1801 return reqs |
1492 | 1802 |
1803 | |
1493 _lfscheme = 'largefile://' | 1804 _lfscheme = 'largefile://' |
1805 | |
1494 | 1806 |
1495 @eh.wrapfunction(urlmod, 'open') | 1807 @eh.wrapfunction(urlmod, 'open') |
1496 def openlargefile(orig, ui, url_, data=None): | 1808 def openlargefile(orig, ui, url_, data=None): |
1497 if url_.startswith(_lfscheme): | 1809 if url_.startswith(_lfscheme): |
1498 if data: | 1810 if data: |
1499 msg = "cannot use data on a 'largefile://' url" | 1811 msg = "cannot use data on a 'largefile://' url" |
1500 raise error.ProgrammingError(msg) | 1812 raise error.ProgrammingError(msg) |
1501 lfid = url_[len(_lfscheme):] | 1813 lfid = url_[len(_lfscheme) :] |
1502 return storefactory.getlfile(ui, lfid) | 1814 return storefactory.getlfile(ui, lfid) |
1503 else: | 1815 else: |
1504 return orig(ui, url_, data=data) | 1816 return orig(ui, url_, data=data) |