##// END OF EJS Templates
py3: make largefiles/overrides.py use absolute_import
liscju -
r29311:b76abae7 default
parent child Browse files
Show More
@@ -1,1419 +1,1433
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''Overridden Mercurial commands and functions for the largefiles extension'''
10 from __future__ import absolute_import
10 11
11 import os
12 12 import copy
13 import os
13 14
14 from mercurial import hg, util, cmdutil, scmutil, match as match_, \
15 archival, pathutil, registrar, revset, error
16 15 from mercurial.i18n import _
17 16
18 import lfutil
19 import lfcommands
20 import storefactory
17 from mercurial import (
18 archival,
19 cmdutil,
20 error,
21 hg,
22 match as match_,
23 pathutil,
24 registrar,
25 revset,
26 scmutil,
27 util,
28 )
29
30 from . import (
31 lfcommands,
32 lfutil,
33 storefactory,
34 )
21 35
22 36 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 37
24 38 def composelargefilematcher(match, manifest):
25 39 '''create a matcher that matches only the largefiles in the original
26 40 matcher'''
27 41 m = copy.copy(match)
28 42 lfile = lambda f: lfutil.standin(f) in manifest
29 43 m._files = filter(lfile, m._files)
30 44 m._fileroots = set(m._files)
31 45 m._always = False
32 46 origmatchfn = m.matchfn
33 47 m.matchfn = lambda f: lfile(f) and origmatchfn(f)
34 48 return m
35 49
36 50 def composenormalfilematcher(match, manifest, exclude=None):
37 51 excluded = set()
38 52 if exclude is not None:
39 53 excluded.update(exclude)
40 54
41 55 m = copy.copy(match)
42 56 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
43 57 manifest or f in excluded)
44 58 m._files = filter(notlfile, m._files)
45 59 m._fileroots = set(m._files)
46 60 m._always = False
47 61 origmatchfn = m.matchfn
48 62 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
49 63 return m
50 64
51 65 def installnormalfilesmatchfn(manifest):
52 66 '''installmatchfn with a matchfn that ignores all largefiles'''
53 67 def overridematch(ctx, pats=(), opts=None, globbed=False,
54 68 default='relpath', badfn=None):
55 69 if opts is None:
56 70 opts = {}
57 71 match = oldmatch(ctx, pats, opts, globbed, default, badfn=badfn)
58 72 return composenormalfilematcher(match, manifest)
59 73 oldmatch = installmatchfn(overridematch)
60 74
61 75 def installmatchfn(f):
62 76 '''monkey patch the scmutil module with a custom match function.
63 77 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
64 78 oldmatch = scmutil.match
65 79 setattr(f, 'oldmatch', oldmatch)
66 80 scmutil.match = f
67 81 return oldmatch
68 82
69 83 def restorematchfn():
70 84 '''restores scmutil.match to what it was before installmatchfn
71 85 was called. no-op if scmutil.match is its original function.
72 86
73 87 Note that n calls to installmatchfn will require n calls to
74 88 restore the original matchfn.'''
75 89 scmutil.match = getattr(scmutil.match, 'oldmatch')
76 90
77 91 def installmatchandpatsfn(f):
78 92 oldmatchandpats = scmutil.matchandpats
79 93 setattr(f, 'oldmatchandpats', oldmatchandpats)
80 94 scmutil.matchandpats = f
81 95 return oldmatchandpats
82 96
83 97 def restorematchandpatsfn():
84 98 '''restores scmutil.matchandpats to what it was before
85 99 installmatchandpatsfn was called. No-op if scmutil.matchandpats
86 100 is its original function.
87 101
88 102 Note that n calls to installmatchandpatsfn will require n calls
89 103 to restore the original matchfn.'''
90 104 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
91 105 scmutil.matchandpats)
92 106
93 107 def addlargefiles(ui, repo, isaddremove, matcher, **opts):
94 108 large = opts.get('large')
95 109 lfsize = lfutil.getminsize(
96 110 ui, lfutil.islfilesrepo(repo), opts.get('lfsize'))
97 111
98 112 lfmatcher = None
99 113 if lfutil.islfilesrepo(repo):
100 114 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
101 115 if lfpats:
102 116 lfmatcher = match_.match(repo.root, '', list(lfpats))
103 117
104 118 lfnames = []
105 119 m = matcher
106 120
107 121 wctx = repo[None]
108 122 for f in repo.walk(match_.badmatch(m, lambda x, y: None)):
109 123 exact = m.exact(f)
110 124 lfile = lfutil.standin(f) in wctx
111 125 nfile = f in wctx
112 126 exists = lfile or nfile
113 127
114 128 # addremove in core gets fancy with the name, add doesn't
115 129 if isaddremove:
116 130 name = m.uipath(f)
117 131 else:
118 132 name = m.rel(f)
119 133
120 134 # Don't warn the user when they attempt to add a normal tracked file.
121 135 # The normal add code will do that for us.
122 136 if exact and exists:
123 137 if lfile:
124 138 ui.warn(_('%s already a largefile\n') % name)
125 139 continue
126 140
127 141 if (exact or not exists) and not lfutil.isstandin(f):
128 142 # In case the file was removed previously, but not committed
129 143 # (issue3507)
130 144 if not repo.wvfs.exists(f):
131 145 continue
132 146
133 147 abovemin = (lfsize and
134 148 repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024)
135 149 if large or abovemin or (lfmatcher and lfmatcher(f)):
136 150 lfnames.append(f)
137 151 if ui.verbose or not exact:
138 152 ui.status(_('adding %s as a largefile\n') % name)
139 153
140 154 bad = []
141 155
142 156 # Need to lock, otherwise there could be a race condition between
143 157 # when standins are created and added to the repo.
144 158 with repo.wlock():
145 159 if not opts.get('dry_run'):
146 160 standins = []
147 161 lfdirstate = lfutil.openlfdirstate(ui, repo)
148 162 for f in lfnames:
149 163 standinname = lfutil.standin(f)
150 164 lfutil.writestandin(repo, standinname, hash='',
151 165 executable=lfutil.getexecutable(repo.wjoin(f)))
152 166 standins.append(standinname)
153 167 if lfdirstate[f] == 'r':
154 168 lfdirstate.normallookup(f)
155 169 else:
156 170 lfdirstate.add(f)
157 171 lfdirstate.write()
158 172 bad += [lfutil.splitstandin(f)
159 173 for f in repo[None].add(standins)
160 174 if f in m.files()]
161 175
162 176 added = [f for f in lfnames if f not in bad]
163 177 return added, bad
164 178
165 179 def removelargefiles(ui, repo, isaddremove, matcher, **opts):
166 180 after = opts.get('after')
167 181 m = composelargefilematcher(matcher, repo[None].manifest())
168 182 try:
169 183 repo.lfstatus = True
170 184 s = repo.status(match=m, clean=not isaddremove)
171 185 finally:
172 186 repo.lfstatus = False
173 187 manifest = repo[None].manifest()
174 188 modified, added, deleted, clean = [[f for f in list
175 189 if lfutil.standin(f) in manifest]
176 190 for list in (s.modified, s.added,
177 191 s.deleted, s.clean)]
178 192
179 193 def warn(files, msg):
180 194 for f in files:
181 195 ui.warn(msg % m.rel(f))
182 196 return int(len(files) > 0)
183 197
184 198 result = 0
185 199
186 200 if after:
187 201 remove = deleted
188 202 result = warn(modified + added + clean,
189 203 _('not removing %s: file still exists\n'))
190 204 else:
191 205 remove = deleted + clean
192 206 result = warn(modified, _('not removing %s: file is modified (use -f'
193 207 ' to force removal)\n'))
194 208 result = warn(added, _('not removing %s: file has been marked for add'
195 209 ' (use forget to undo)\n')) or result
196 210
197 211 # Need to lock because standin files are deleted then removed from the
198 212 # repository and we could race in-between.
199 213 with repo.wlock():
200 214 lfdirstate = lfutil.openlfdirstate(ui, repo)
201 215 for f in sorted(remove):
202 216 if ui.verbose or not m.exact(f):
203 217 # addremove in core gets fancy with the name, remove doesn't
204 218 if isaddremove:
205 219 name = m.uipath(f)
206 220 else:
207 221 name = m.rel(f)
208 222 ui.status(_('removing %s\n') % name)
209 223
210 224 if not opts.get('dry_run'):
211 225 if not after:
212 226 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
213 227
214 228 if opts.get('dry_run'):
215 229 return result
216 230
217 231 remove = [lfutil.standin(f) for f in remove]
218 232 # If this is being called by addremove, let the original addremove
219 233 # function handle this.
220 234 if not isaddremove:
221 235 for f in remove:
222 236 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
223 237 repo[None].forget(remove)
224 238
225 239 for f in remove:
226 240 lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f),
227 241 False)
228 242
229 243 lfdirstate.write()
230 244
231 245 return result
232 246
233 247 # For overriding mercurial.hgweb.webcommands so that largefiles will
234 248 # appear at their right place in the manifests.
235 249 def decodepath(orig, path):
236 250 return lfutil.splitstandin(path) or path
237 251
238 252 # -- Wrappers: modify existing commands --------------------------------
239 253
240 254 def overrideadd(orig, ui, repo, *pats, **opts):
241 255 if opts.get('normal') and opts.get('large'):
242 256 raise error.Abort(_('--normal cannot be used with --large'))
243 257 return orig(ui, repo, *pats, **opts)
244 258
245 259 def cmdutiladd(orig, ui, repo, matcher, prefix, explicitonly, **opts):
246 260 # The --normal flag short circuits this override
247 261 if opts.get('normal'):
248 262 return orig(ui, repo, matcher, prefix, explicitonly, **opts)
249 263
250 264 ladded, lbad = addlargefiles(ui, repo, False, matcher, **opts)
251 265 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(),
252 266 ladded)
253 267 bad = orig(ui, repo, normalmatcher, prefix, explicitonly, **opts)
254 268
255 269 bad.extend(f for f in lbad)
256 270 return bad
257 271
258 272 def cmdutilremove(orig, ui, repo, matcher, prefix, after, force, subrepos):
259 273 normalmatcher = composenormalfilematcher(matcher, repo[None].manifest())
260 274 result = orig(ui, repo, normalmatcher, prefix, after, force, subrepos)
261 275 return removelargefiles(ui, repo, False, matcher, after=after,
262 276 force=force) or result
263 277
264 278 def overridestatusfn(orig, repo, rev2, **opts):
265 279 try:
266 280 repo._repo.lfstatus = True
267 281 return orig(repo, rev2, **opts)
268 282 finally:
269 283 repo._repo.lfstatus = False
270 284
271 285 def overridestatus(orig, ui, repo, *pats, **opts):
272 286 try:
273 287 repo.lfstatus = True
274 288 return orig(ui, repo, *pats, **opts)
275 289 finally:
276 290 repo.lfstatus = False
277 291
278 292 def overridedirty(orig, repo, ignoreupdate=False):
279 293 try:
280 294 repo._repo.lfstatus = True
281 295 return orig(repo, ignoreupdate)
282 296 finally:
283 297 repo._repo.lfstatus = False
284 298
285 299 def overridelog(orig, ui, repo, *pats, **opts):
286 300 def overridematchandpats(ctx, pats=(), opts=None, globbed=False,
287 301 default='relpath', badfn=None):
288 302 """Matcher that merges root directory with .hglf, suitable for log.
289 303 It is still possible to match .hglf directly.
290 304 For any listed files run log on the standin too.
291 305 matchfn tries both the given filename and with .hglf stripped.
292 306 """
293 307 if opts is None:
294 308 opts = {}
295 309 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default,
296 310 badfn=badfn)
297 311 m, p = copy.copy(matchandpats)
298 312
299 313 if m.always():
300 314 # We want to match everything anyway, so there's no benefit trying
301 315 # to add standins.
302 316 return matchandpats
303 317
304 318 pats = set(p)
305 319
306 320 def fixpats(pat, tostandin=lfutil.standin):
307 321 if pat.startswith('set:'):
308 322 return pat
309 323
310 324 kindpat = match_._patsplit(pat, None)
311 325
312 326 if kindpat[0] is not None:
313 327 return kindpat[0] + ':' + tostandin(kindpat[1])
314 328 return tostandin(kindpat[1])
315 329
316 330 if m._cwd:
317 331 hglf = lfutil.shortname
318 332 back = util.pconvert(m.rel(hglf)[:-len(hglf)])
319 333
320 334 def tostandin(f):
321 335 # The file may already be a standin, so truncate the back
322 336 # prefix and test before mangling it. This avoids turning
323 337 # 'glob:../.hglf/foo*' into 'glob:../.hglf/../.hglf/foo*'.
324 338 if f.startswith(back) and lfutil.splitstandin(f[len(back):]):
325 339 return f
326 340
327 341 # An absolute path is from outside the repo, so truncate the
328 342 # path to the root before building the standin. Otherwise cwd
329 343 # is somewhere in the repo, relative to root, and needs to be
330 344 # prepended before building the standin.
331 345 if os.path.isabs(m._cwd):
332 346 f = f[len(back):]
333 347 else:
334 348 f = m._cwd + '/' + f
335 349 return back + lfutil.standin(f)
336 350
337 351 pats.update(fixpats(f, tostandin) for f in p)
338 352 else:
339 353 def tostandin(f):
340 354 if lfutil.splitstandin(f):
341 355 return f
342 356 return lfutil.standin(f)
343 357 pats.update(fixpats(f, tostandin) for f in p)
344 358
345 359 for i in range(0, len(m._files)):
346 360 # Don't add '.hglf' to m.files, since that is already covered by '.'
347 361 if m._files[i] == '.':
348 362 continue
349 363 standin = lfutil.standin(m._files[i])
350 364 # If the "standin" is a directory, append instead of replace to
351 365 # support naming a directory on the command line with only
352 366 # largefiles. The original directory is kept to support normal
353 367 # files.
354 368 if standin in repo[ctx.node()]:
355 369 m._files[i] = standin
356 370 elif m._files[i] not in repo[ctx.node()] \
357 371 and repo.wvfs.isdir(standin):
358 372 m._files.append(standin)
359 373
360 374 m._fileroots = set(m._files)
361 375 m._always = False
362 376 origmatchfn = m.matchfn
363 377 def lfmatchfn(f):
364 378 lf = lfutil.splitstandin(f)
365 379 if lf is not None and origmatchfn(lf):
366 380 return True
367 381 r = origmatchfn(f)
368 382 return r
369 383 m.matchfn = lfmatchfn
370 384
371 385 ui.debug('updated patterns: %s\n' % sorted(pats))
372 386 return m, pats
373 387
374 388 # For hg log --patch, the match object is used in two different senses:
375 389 # (1) to determine what revisions should be printed out, and
376 390 # (2) to determine what files to print out diffs for.
377 391 # The magic matchandpats override should be used for case (1) but not for
378 392 # case (2).
379 393 def overridemakelogfilematcher(repo, pats, opts, badfn=None):
380 394 wctx = repo[None]
381 395 match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn)
382 396 return lambda rev: match
383 397
384 398 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
385 399 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
386 400 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
387 401
388 402 try:
389 403 return orig(ui, repo, *pats, **opts)
390 404 finally:
391 405 restorematchandpatsfn()
392 406 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
393 407
394 408 def overrideverify(orig, ui, repo, *pats, **opts):
395 409 large = opts.pop('large', False)
396 410 all = opts.pop('lfa', False)
397 411 contents = opts.pop('lfc', False)
398 412
399 413 result = orig(ui, repo, *pats, **opts)
400 414 if large or all or contents:
401 415 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
402 416 return result
403 417
404 418 def overridedebugstate(orig, ui, repo, *pats, **opts):
405 419 large = opts.pop('large', False)
406 420 if large:
407 421 class fakerepo(object):
408 422 dirstate = lfutil.openlfdirstate(ui, repo)
409 423 orig(ui, fakerepo, *pats, **opts)
410 424 else:
411 425 orig(ui, repo, *pats, **opts)
412 426
413 427 # Before starting the manifest merge, merge.updates will call
414 428 # _checkunknownfile to check if there are any files in the merged-in
415 429 # changeset that collide with unknown files in the working copy.
416 430 #
417 431 # The largefiles are seen as unknown, so this prevents us from merging
418 432 # in a file 'foo' if we already have a largefile with the same name.
419 433 #
420 434 # The overridden function filters the unknown files by removing any
421 435 # largefiles. This makes the merge proceed and we can then handle this
422 436 # case further in the overridden calculateupdates function below.
423 437 def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None):
424 438 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
425 439 return False
426 440 return origfn(repo, wctx, mctx, f, f2)
427 441
428 442 # The manifest merge handles conflicts on the manifest level. We want
429 443 # to handle changes in largefile-ness of files at this level too.
430 444 #
431 445 # The strategy is to run the original calculateupdates and then process
432 446 # the action list it outputs. There are two cases we need to deal with:
433 447 #
434 448 # 1. Normal file in p1, largefile in p2. Here the largefile is
435 449 # detected via its standin file, which will enter the working copy
436 450 # with a "get" action. It is not "merge" since the standin is all
437 451 # Mercurial is concerned with at this level -- the link to the
438 452 # existing normal file is not relevant here.
439 453 #
440 454 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
441 455 # since the largefile will be present in the working copy and
442 456 # different from the normal file in p2. Mercurial therefore
443 457 # triggers a merge action.
444 458 #
445 459 # In both cases, we prompt the user and emit new actions to either
446 460 # remove the standin (if the normal file was kept) or to remove the
447 461 # normal file and get the standin (if the largefile was kept). The
448 462 # default prompt answer is to use the largefile version since it was
449 463 # presumably changed on purpose.
450 464 #
451 465 # Finally, the merge.applyupdates function will then take care of
452 466 # writing the files into the working copy and lfcommands.updatelfiles
453 467 # will update the largefiles.
454 468 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
455 469 acceptremote, *args, **kwargs):
456 470 overwrite = force and not branchmerge
457 471 actions, diverge, renamedelete = origfn(
458 472 repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs)
459 473
460 474 if overwrite:
461 475 return actions, diverge, renamedelete
462 476
463 477 # Convert to dictionary with filename as key and action as value.
464 478 lfiles = set()
465 479 for f in actions:
466 480 splitstandin = lfutil.splitstandin(f)
467 481 if splitstandin in p1:
468 482 lfiles.add(splitstandin)
469 483 elif lfutil.standin(f) in p1:
470 484 lfiles.add(f)
471 485
472 486 for lfile in sorted(lfiles):
473 487 standin = lfutil.standin(lfile)
474 488 (lm, largs, lmsg) = actions.get(lfile, (None, None, None))
475 489 (sm, sargs, smsg) = actions.get(standin, (None, None, None))
476 490 if sm in ('g', 'dc') and lm != 'r':
477 491 if sm == 'dc':
478 492 f1, f2, fa, move, anc = sargs
479 493 sargs = (p2[f2].flags(), False)
480 494 # Case 1: normal file in the working copy, largefile in
481 495 # the second parent
482 496 usermsg = _('remote turned local normal file %s into a largefile\n'
483 497 'use (l)argefile or keep (n)ormal file?'
484 498 '$$ &Largefile $$ &Normal file') % lfile
485 499 if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile
486 500 actions[lfile] = ('r', None, 'replaced by standin')
487 501 actions[standin] = ('g', sargs, 'replaces standin')
488 502 else: # keep local normal file
489 503 actions[lfile] = ('k', None, 'replaces standin')
490 504 if branchmerge:
491 505 actions[standin] = ('k', None, 'replaced by non-standin')
492 506 else:
493 507 actions[standin] = ('r', None, 'replaced by non-standin')
494 508 elif lm in ('g', 'dc') and sm != 'r':
495 509 if lm == 'dc':
496 510 f1, f2, fa, move, anc = largs
497 511 largs = (p2[f2].flags(), False)
498 512 # Case 2: largefile in the working copy, normal file in
499 513 # the second parent
500 514 usermsg = _('remote turned local largefile %s into a normal file\n'
501 515 'keep (l)argefile or use (n)ormal file?'
502 516 '$$ &Largefile $$ &Normal file') % lfile
503 517 if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile
504 518 if branchmerge:
505 519 # largefile can be restored from standin safely
506 520 actions[lfile] = ('k', None, 'replaced by standin')
507 521 actions[standin] = ('k', None, 'replaces standin')
508 522 else:
509 523 # "lfile" should be marked as "removed" without
510 524 # removal of itself
511 525 actions[lfile] = ('lfmr', None,
512 526 'forget non-standin largefile')
513 527
514 528 # linear-merge should treat this largefile as 're-added'
515 529 actions[standin] = ('a', None, 'keep standin')
516 530 else: # pick remote normal file
517 531 actions[lfile] = ('g', largs, 'replaces standin')
518 532 actions[standin] = ('r', None, 'replaced by non-standin')
519 533
520 534 return actions, diverge, renamedelete
521 535
522 536 def mergerecordupdates(orig, repo, actions, branchmerge):
523 537 if 'lfmr' in actions:
524 538 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
525 539 for lfile, args, msg in actions['lfmr']:
526 540 # this should be executed before 'orig', to execute 'remove'
527 541 # before all other actions
528 542 repo.dirstate.remove(lfile)
529 543 # make sure lfile doesn't get synclfdirstate'd as normal
530 544 lfdirstate.add(lfile)
531 545 lfdirstate.write()
532 546
533 547 return orig(repo, actions, branchmerge)
534 548
535 549
536 550 # Override filemerge to prompt the user about how they wish to merge
537 551 # largefiles. This will handle identical edits without prompting the user.
538 552 def overridefilemerge(origfn, premerge, repo, mynode, orig, fcd, fco, fca,
539 553 labels=None):
540 554 if not lfutil.isstandin(orig) or fcd.isabsent() or fco.isabsent():
541 555 return origfn(premerge, repo, mynode, orig, fcd, fco, fca,
542 556 labels=labels)
543 557
544 558 ahash = fca.data().strip().lower()
545 559 dhash = fcd.data().strip().lower()
546 560 ohash = fco.data().strip().lower()
547 561 if (ohash != ahash and
548 562 ohash != dhash and
549 563 (dhash == ahash or
550 564 repo.ui.promptchoice(
551 565 _('largefile %s has a merge conflict\nancestor was %s\n'
552 566 'keep (l)ocal %s or\ntake (o)ther %s?'
553 567 '$$ &Local $$ &Other') %
554 568 (lfutil.splitstandin(orig), ahash, dhash, ohash),
555 569 0) == 1)):
556 570 repo.wwrite(fcd.path(), fco.data(), fco.flags())
557 571 return True, 0, False
558 572
559 573 def copiespathcopies(orig, ctx1, ctx2, match=None):
560 574 copies = orig(ctx1, ctx2, match=match)
561 575 updated = {}
562 576
563 577 for k, v in copies.iteritems():
564 578 updated[lfutil.splitstandin(k) or k] = lfutil.splitstandin(v) or v
565 579
566 580 return updated
567 581
568 582 # Copy first changes the matchers to match standins instead of
569 583 # largefiles. Then it overrides util.copyfile in that function it
570 584 # checks if the destination largefile already exists. It also keeps a
571 585 # list of copied files so that the largefiles can be copied and the
572 586 # dirstate updated.
573 587 def overridecopy(orig, ui, repo, pats, opts, rename=False):
574 588 # doesn't remove largefile on rename
575 589 if len(pats) < 2:
576 590 # this isn't legal, let the original function deal with it
577 591 return orig(ui, repo, pats, opts, rename)
578 592
579 593 # This could copy both lfiles and normal files in one command,
580 594 # but we don't want to do that. First replace their matcher to
581 595 # only match normal files and run it, then replace it to just
582 596 # match largefiles and run it again.
583 597 nonormalfiles = False
584 598 nolfiles = False
585 599 installnormalfilesmatchfn(repo[None].manifest())
586 600 try:
587 601 result = orig(ui, repo, pats, opts, rename)
588 602 except error.Abort as e:
589 603 if str(e) != _('no files to copy'):
590 604 raise e
591 605 else:
592 606 nonormalfiles = True
593 607 result = 0
594 608 finally:
595 609 restorematchfn()
596 610
597 611 # The first rename can cause our current working directory to be removed.
598 612 # In that case there is nothing left to copy/rename so just quit.
599 613 try:
600 614 repo.getcwd()
601 615 except OSError:
602 616 return result
603 617
604 618 def makestandin(relpath):
605 619 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
606 620 return repo.wvfs.join(lfutil.standin(path))
607 621
608 622 fullpats = scmutil.expandpats(pats)
609 623 dest = fullpats[-1]
610 624
611 625 if os.path.isdir(dest):
612 626 if not os.path.isdir(makestandin(dest)):
613 627 os.makedirs(makestandin(dest))
614 628
615 629 try:
616 630 # When we call orig below it creates the standins but we don't add
617 631 # them to the dir state until later so lock during that time.
618 632 wlock = repo.wlock()
619 633
620 634 manifest = repo[None].manifest()
621 635 def overridematch(ctx, pats=(), opts=None, globbed=False,
622 636 default='relpath', badfn=None):
623 637 if opts is None:
624 638 opts = {}
625 639 newpats = []
626 640 # The patterns were previously mangled to add the standin
627 641 # directory; we need to remove that now
628 642 for pat in pats:
629 643 if match_.patkind(pat) is None and lfutil.shortname in pat:
630 644 newpats.append(pat.replace(lfutil.shortname, ''))
631 645 else:
632 646 newpats.append(pat)
633 647 match = oldmatch(ctx, newpats, opts, globbed, default, badfn=badfn)
634 648 m = copy.copy(match)
635 649 lfile = lambda f: lfutil.standin(f) in manifest
636 650 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
637 651 m._fileroots = set(m._files)
638 652 origmatchfn = m.matchfn
639 653 m.matchfn = lambda f: (lfutil.isstandin(f) and
640 654 (f in manifest) and
641 655 origmatchfn(lfutil.splitstandin(f)) or
642 656 None)
643 657 return m
644 658 oldmatch = installmatchfn(overridematch)
645 659 listpats = []
646 660 for pat in pats:
647 661 if match_.patkind(pat) is not None:
648 662 listpats.append(pat)
649 663 else:
650 664 listpats.append(makestandin(pat))
651 665
652 666 try:
653 667 origcopyfile = util.copyfile
654 668 copiedfiles = []
655 669 def overridecopyfile(src, dest):
656 670 if (lfutil.shortname in src and
657 671 dest.startswith(repo.wjoin(lfutil.shortname))):
658 672 destlfile = dest.replace(lfutil.shortname, '')
659 673 if not opts['force'] and os.path.exists(destlfile):
660 674 raise IOError('',
661 675 _('destination largefile already exists'))
662 676 copiedfiles.append((src, dest))
663 677 origcopyfile(src, dest)
664 678
665 679 util.copyfile = overridecopyfile
666 680 result += orig(ui, repo, listpats, opts, rename)
667 681 finally:
668 682 util.copyfile = origcopyfile
669 683
670 684 lfdirstate = lfutil.openlfdirstate(ui, repo)
671 685 for (src, dest) in copiedfiles:
672 686 if (lfutil.shortname in src and
673 687 dest.startswith(repo.wjoin(lfutil.shortname))):
674 688 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
675 689 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
676 690 destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or '.'
677 691 if not os.path.isdir(destlfiledir):
678 692 os.makedirs(destlfiledir)
679 693 if rename:
680 694 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
681 695
682 696 # The file is gone, but this deletes any empty parent
683 697 # directories as a side-effect.
684 698 util.unlinkpath(repo.wjoin(srclfile), True)
685 699 lfdirstate.remove(srclfile)
686 700 else:
687 701 util.copyfile(repo.wjoin(srclfile),
688 702 repo.wjoin(destlfile))
689 703
690 704 lfdirstate.add(destlfile)
691 705 lfdirstate.write()
692 706 except error.Abort as e:
693 707 if str(e) != _('no files to copy'):
694 708 raise e
695 709 else:
696 710 nolfiles = True
697 711 finally:
698 712 restorematchfn()
699 713 wlock.release()
700 714
701 715 if nolfiles and nonormalfiles:
702 716 raise error.Abort(_('no files to copy'))
703 717
704 718 return result
705 719
706 720 # When the user calls revert, we have to be careful to not revert any
707 721 # changes to other largefiles accidentally. This means we have to keep
708 722 # track of the largefiles that are being reverted so we only pull down
709 723 # the necessary largefiles.
710 724 #
711 725 # Standins are only updated (to match the hash of largefiles) before
712 726 # commits. Update the standins then run the original revert, changing
713 727 # the matcher to hit standins instead of largefiles. Based on the
714 728 # resulting standins update the largefiles.
715 729 def overriderevert(orig, ui, repo, ctx, parents, *pats, **opts):
716 730 # Because we put the standins in a bad state (by updating them)
717 731 # and then return them to a correct state we need to lock to
718 732 # prevent others from changing them in their incorrect state.
719 733 with repo.wlock():
720 734 lfdirstate = lfutil.openlfdirstate(ui, repo)
721 735 s = lfutil.lfdirstatestatus(lfdirstate, repo)
722 736 lfdirstate.write()
723 737 for lfile in s.modified:
724 738 lfutil.updatestandin(repo, lfutil.standin(lfile))
725 739 for lfile in s.deleted:
726 740 if (repo.wvfs.exists(lfutil.standin(lfile))):
727 741 repo.wvfs.unlink(lfutil.standin(lfile))
728 742
729 743 oldstandins = lfutil.getstandinsstate(repo)
730 744
731 745 def overridematch(mctx, pats=(), opts=None, globbed=False,
732 746 default='relpath', badfn=None):
733 747 if opts is None:
734 748 opts = {}
735 749 match = oldmatch(mctx, pats, opts, globbed, default, badfn=badfn)
736 750 m = copy.copy(match)
737 751
738 752 # revert supports recursing into subrepos, and though largefiles
739 753 # currently doesn't work correctly in that case, this match is
740 754 # called, so the lfdirstate above may not be the correct one for
741 755 # this invocation of match.
742 756 lfdirstate = lfutil.openlfdirstate(mctx.repo().ui, mctx.repo(),
743 757 False)
744 758
745 759 def tostandin(f):
746 760 standin = lfutil.standin(f)
747 761 if standin in ctx or standin in mctx:
748 762 return standin
749 763 elif standin in repo[None] or lfdirstate[f] == 'r':
750 764 return None
751 765 return f
752 766 m._files = [tostandin(f) for f in m._files]
753 767 m._files = [f for f in m._files if f is not None]
754 768 m._fileroots = set(m._files)
755 769 origmatchfn = m.matchfn
756 770 def matchfn(f):
757 771 if lfutil.isstandin(f):
758 772 return (origmatchfn(lfutil.splitstandin(f)) and
759 773 (f in ctx or f in mctx))
760 774 return origmatchfn(f)
761 775 m.matchfn = matchfn
762 776 return m
763 777 oldmatch = installmatchfn(overridematch)
764 778 try:
765 779 orig(ui, repo, ctx, parents, *pats, **opts)
766 780 finally:
767 781 restorematchfn()
768 782
769 783 newstandins = lfutil.getstandinsstate(repo)
770 784 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
771 785 # lfdirstate should be 'normallookup'-ed for updated files,
772 786 # because reverting doesn't touch dirstate for 'normal' files
773 787 # when target revision is explicitly specified: in such case,
774 788 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
775 789 # of target (standin) file.
776 790 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
777 791 normallookup=True)
778 792
779 793 # after pulling changesets, we need to take some extra care to get
780 794 # largefiles updated remotely
781 795 def overridepull(orig, ui, repo, source=None, **opts):
782 796 revsprepull = len(repo)
783 797 if not source:
784 798 source = 'default'
785 799 repo.lfpullsource = source
786 800 result = orig(ui, repo, source, **opts)
787 801 revspostpull = len(repo)
788 802 lfrevs = opts.get('lfrev', [])
789 803 if opts.get('all_largefiles'):
790 804 lfrevs.append('pulled()')
791 805 if lfrevs and revspostpull > revsprepull:
792 806 numcached = 0
793 807 repo.firstpulled = revsprepull # for pulled() revset expression
794 808 try:
795 809 for rev in scmutil.revrange(repo, lfrevs):
796 810 ui.note(_('pulling largefiles for revision %s\n') % rev)
797 811 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
798 812 numcached += len(cached)
799 813 finally:
800 814 del repo.firstpulled
801 815 ui.status(_("%d largefiles cached\n") % numcached)
802 816 return result
803 817
804 818 def overridepush(orig, ui, repo, *args, **kwargs):
805 819 """Override push command and store --lfrev parameters in opargs"""
806 820 lfrevs = kwargs.pop('lfrev', None)
807 821 if lfrevs:
808 822 opargs = kwargs.setdefault('opargs', {})
809 823 opargs['lfrevs'] = scmutil.revrange(repo, lfrevs)
810 824 return orig(ui, repo, *args, **kwargs)
811 825
812 826 def exchangepushoperation(orig, *args, **kwargs):
813 827 """Override pushoperation constructor and store lfrevs parameter"""
814 828 lfrevs = kwargs.pop('lfrevs', None)
815 829 pushop = orig(*args, **kwargs)
816 830 pushop.lfrevs = lfrevs
817 831 return pushop
818 832
819 833 revsetpredicate = registrar.revsetpredicate()
820 834
821 835 @revsetpredicate('pulled()')
822 836 def pulledrevsetsymbol(repo, subset, x):
823 837 """Changesets that just has been pulled.
824 838
825 839 Only available with largefiles from pull --lfrev expressions.
826 840
827 841 .. container:: verbose
828 842
829 843 Some examples:
830 844
831 845 - pull largefiles for all new changesets::
832 846
833 847 hg pull -lfrev "pulled()"
834 848
835 849 - pull largefiles for all new branch heads::
836 850
837 851 hg pull -lfrev "head(pulled()) and not closed()"
838 852
839 853 """
840 854
841 855 try:
842 856 firstpulled = repo.firstpulled
843 857 except AttributeError:
844 858 raise error.Abort(_("pulled() only available in --lfrev"))
845 859 return revset.baseset([r for r in subset if r >= firstpulled])
846 860
847 861 def overrideclone(orig, ui, source, dest=None, **opts):
848 862 d = dest
849 863 if d is None:
850 864 d = hg.defaultdest(source)
851 865 if opts.get('all_largefiles') and not hg.islocal(d):
852 866 raise error.Abort(_(
853 867 '--all-largefiles is incompatible with non-local destination %s') %
854 868 d)
855 869
856 870 return orig(ui, source, dest, **opts)
857 871
858 872 def hgclone(orig, ui, opts, *args, **kwargs):
859 873 result = orig(ui, opts, *args, **kwargs)
860 874
861 875 if result is not None:
862 876 sourcerepo, destrepo = result
863 877 repo = destrepo.local()
864 878
865 879 # When cloning to a remote repo (like through SSH), no repo is available
866 880 # from the peer. Therefore the largefiles can't be downloaded and the
867 881 # hgrc can't be updated.
868 882 if not repo:
869 883 return result
870 884
871 885 # If largefiles is required for this repo, permanently enable it locally
872 886 if 'largefiles' in repo.requirements:
873 887 fp = repo.vfs('hgrc', 'a', text=True)
874 888 try:
875 889 fp.write('\n[extensions]\nlargefiles=\n')
876 890 finally:
877 891 fp.close()
878 892
879 893 # Caching is implicitly limited to 'rev' option, since the dest repo was
880 894 # truncated at that point. The user may expect a download count with
881 895 # this option, so attempt whether or not this is a largefile repo.
882 896 if opts.get('all_largefiles'):
883 897 success, missing = lfcommands.downloadlfiles(ui, repo, None)
884 898
885 899 if missing != 0:
886 900 return None
887 901
888 902 return result
889 903
890 904 def overriderebase(orig, ui, repo, **opts):
891 905 if not util.safehasattr(repo, '_largefilesenabled'):
892 906 return orig(ui, repo, **opts)
893 907
894 908 resuming = opts.get('continue')
895 909 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
896 910 repo._lfstatuswriters.append(lambda *msg, **opts: None)
897 911 try:
898 912 return orig(ui, repo, **opts)
899 913 finally:
900 914 repo._lfstatuswriters.pop()
901 915 repo._lfcommithooks.pop()
902 916
903 917 def overridearchivecmd(orig, ui, repo, dest, **opts):
904 918 repo.unfiltered().lfstatus = True
905 919
906 920 try:
907 921 return orig(ui, repo.unfiltered(), dest, **opts)
908 922 finally:
909 923 repo.unfiltered().lfstatus = False
910 924
911 925 def hgwebarchive(orig, web, req, tmpl):
912 926 web.repo.lfstatus = True
913 927
914 928 try:
915 929 return orig(web, req, tmpl)
916 930 finally:
917 931 web.repo.lfstatus = False
918 932
919 933 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
920 934 prefix='', mtime=None, subrepos=None):
921 935 # For some reason setting repo.lfstatus in hgwebarchive only changes the
922 936 # unfiltered repo's attr, so check that as well.
923 937 if not repo.lfstatus and not repo.unfiltered().lfstatus:
924 938 return orig(repo, dest, node, kind, decode, matchfn, prefix, mtime,
925 939 subrepos)
926 940
927 941 # No need to lock because we are only reading history and
928 942 # largefile caches, neither of which are modified.
929 943 if node is not None:
930 944 lfcommands.cachelfiles(repo.ui, repo, node)
931 945
932 946 if kind not in archival.archivers:
933 947 raise error.Abort(_("unknown archive type '%s'") % kind)
934 948
935 949 ctx = repo[node]
936 950
937 951 if kind == 'files':
938 952 if prefix:
939 953 raise error.Abort(
940 954 _('cannot give prefix when archiving to files'))
941 955 else:
942 956 prefix = archival.tidyprefix(dest, kind, prefix)
943 957
944 958 def write(name, mode, islink, getdata):
945 959 if matchfn and not matchfn(name):
946 960 return
947 961 data = getdata()
948 962 if decode:
949 963 data = repo.wwritedata(name, data)
950 964 archiver.addfile(prefix + name, mode, islink, data)
951 965
952 966 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
953 967
954 968 if repo.ui.configbool("ui", "archivemeta", True):
955 969 write('.hg_archival.txt', 0o644, False,
956 970 lambda: archival.buildmetadata(ctx))
957 971
958 972 for f in ctx:
959 973 ff = ctx.flags(f)
960 974 getdata = ctx[f].data
961 975 if lfutil.isstandin(f):
962 976 if node is not None:
963 977 path = lfutil.findfile(repo, getdata().strip())
964 978
965 979 if path is None:
966 980 raise error.Abort(
967 981 _('largefile %s not found in repo store or system cache')
968 982 % lfutil.splitstandin(f))
969 983 else:
970 984 path = lfutil.splitstandin(f)
971 985
972 986 f = lfutil.splitstandin(f)
973 987
974 988 getdata = lambda: util.readfile(path)
975 989 write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, getdata)
976 990
977 991 if subrepos:
978 992 for subpath in sorted(ctx.substate):
979 993 sub = ctx.workingsub(subpath)
980 994 submatch = match_.subdirmatcher(subpath, matchfn)
981 995 sub._repo.lfstatus = True
982 996 sub.archive(archiver, prefix, submatch)
983 997
984 998 archiver.done()
985 999
986 1000 def hgsubrepoarchive(orig, repo, archiver, prefix, match=None):
987 1001 if not repo._repo.lfstatus:
988 1002 return orig(repo, archiver, prefix, match)
989 1003
990 1004 repo._get(repo._state + ('hg',))
991 1005 rev = repo._state[1]
992 1006 ctx = repo._repo[rev]
993 1007
994 1008 if ctx.node() is not None:
995 1009 lfcommands.cachelfiles(repo.ui, repo._repo, ctx.node())
996 1010
997 1011 def write(name, mode, islink, getdata):
998 1012 # At this point, the standin has been replaced with the largefile name,
999 1013 # so the normal matcher works here without the lfutil variants.
1000 1014 if match and not match(f):
1001 1015 return
1002 1016 data = getdata()
1003 1017
1004 1018 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
1005 1019
1006 1020 for f in ctx:
1007 1021 ff = ctx.flags(f)
1008 1022 getdata = ctx[f].data
1009 1023 if lfutil.isstandin(f):
1010 1024 if ctx.node() is not None:
1011 1025 path = lfutil.findfile(repo._repo, getdata().strip())
1012 1026
1013 1027 if path is None:
1014 1028 raise error.Abort(
1015 1029 _('largefile %s not found in repo store or system cache')
1016 1030 % lfutil.splitstandin(f))
1017 1031 else:
1018 1032 path = lfutil.splitstandin(f)
1019 1033
1020 1034 f = lfutil.splitstandin(f)
1021 1035
1022 1036 getdata = lambda: util.readfile(os.path.join(prefix, path))
1023 1037
1024 1038 write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, getdata)
1025 1039
1026 1040 for subpath in sorted(ctx.substate):
1027 1041 sub = ctx.workingsub(subpath)
1028 1042 submatch = match_.subdirmatcher(subpath, match)
1029 1043 sub._repo.lfstatus = True
1030 1044 sub.archive(archiver, prefix + repo._path + '/', submatch)
1031 1045
1032 1046 # If a largefile is modified, the change is not reflected in its
1033 1047 # standin until a commit. cmdutil.bailifchanged() raises an exception
1034 1048 # if the repo has uncommitted changes. Wrap it to also check if
1035 1049 # largefiles were changed. This is used by bisect, backout and fetch.
1036 1050 def overridebailifchanged(orig, repo, *args, **kwargs):
1037 1051 orig(repo, *args, **kwargs)
1038 1052 repo.lfstatus = True
1039 1053 s = repo.status()
1040 1054 repo.lfstatus = False
1041 1055 if s.modified or s.added or s.removed or s.deleted:
1042 1056 raise error.Abort(_('uncommitted changes'))
1043 1057
1044 1058 def postcommitstatus(orig, repo, *args, **kwargs):
1045 1059 repo.lfstatus = True
1046 1060 try:
1047 1061 return orig(repo, *args, **kwargs)
1048 1062 finally:
1049 1063 repo.lfstatus = False
1050 1064
1051 1065 def cmdutilforget(orig, ui, repo, match, prefix, explicitonly):
1052 1066 normalmatcher = composenormalfilematcher(match, repo[None].manifest())
1053 1067 bad, forgot = orig(ui, repo, normalmatcher, prefix, explicitonly)
1054 1068 m = composelargefilematcher(match, repo[None].manifest())
1055 1069
1056 1070 try:
1057 1071 repo.lfstatus = True
1058 1072 s = repo.status(match=m, clean=True)
1059 1073 finally:
1060 1074 repo.lfstatus = False
1061 1075 forget = sorted(s.modified + s.added + s.deleted + s.clean)
1062 1076 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
1063 1077
1064 1078 for f in forget:
1065 1079 if lfutil.standin(f) not in repo.dirstate and not \
1066 1080 repo.wvfs.isdir(lfutil.standin(f)):
1067 1081 ui.warn(_('not removing %s: file is already untracked\n')
1068 1082 % m.rel(f))
1069 1083 bad.append(f)
1070 1084
1071 1085 for f in forget:
1072 1086 if ui.verbose or not m.exact(f):
1073 1087 ui.status(_('removing %s\n') % m.rel(f))
1074 1088
1075 1089 # Need to lock because standin files are deleted then removed from the
1076 1090 # repository and we could race in-between.
1077 1091 with repo.wlock():
1078 1092 lfdirstate = lfutil.openlfdirstate(ui, repo)
1079 1093 for f in forget:
1080 1094 if lfdirstate[f] == 'a':
1081 1095 lfdirstate.drop(f)
1082 1096 else:
1083 1097 lfdirstate.remove(f)
1084 1098 lfdirstate.write()
1085 1099 standins = [lfutil.standin(f) for f in forget]
1086 1100 for f in standins:
1087 1101 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1088 1102 rejected = repo[None].forget(standins)
1089 1103
1090 1104 bad.extend(f for f in rejected if f in m.files())
1091 1105 forgot.extend(f for f in forget if f not in rejected)
1092 1106 return bad, forgot
1093 1107
1094 1108 def _getoutgoings(repo, other, missing, addfunc):
1095 1109 """get pairs of filename and largefile hash in outgoing revisions
1096 1110 in 'missing'.
1097 1111
1098 1112 largefiles already existing on 'other' repository are ignored.
1099 1113
1100 1114 'addfunc' is invoked with each unique pairs of filename and
1101 1115 largefile hash value.
1102 1116 """
1103 1117 knowns = set()
1104 1118 lfhashes = set()
1105 1119 def dedup(fn, lfhash):
1106 1120 k = (fn, lfhash)
1107 1121 if k not in knowns:
1108 1122 knowns.add(k)
1109 1123 lfhashes.add(lfhash)
1110 1124 lfutil.getlfilestoupload(repo, missing, dedup)
1111 1125 if lfhashes:
1112 1126 lfexists = storefactory._openstore(repo, other).exists(lfhashes)
1113 1127 for fn, lfhash in knowns:
1114 1128 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1115 1129 addfunc(fn, lfhash)
1116 1130
1117 1131 def outgoinghook(ui, repo, other, opts, missing):
1118 1132 if opts.pop('large', None):
1119 1133 lfhashes = set()
1120 1134 if ui.debugflag:
1121 1135 toupload = {}
1122 1136 def addfunc(fn, lfhash):
1123 1137 if fn not in toupload:
1124 1138 toupload[fn] = []
1125 1139 toupload[fn].append(lfhash)
1126 1140 lfhashes.add(lfhash)
1127 1141 def showhashes(fn):
1128 1142 for lfhash in sorted(toupload[fn]):
1129 1143 ui.debug(' %s\n' % (lfhash))
1130 1144 else:
1131 1145 toupload = set()
1132 1146 def addfunc(fn, lfhash):
1133 1147 toupload.add(fn)
1134 1148 lfhashes.add(lfhash)
1135 1149 def showhashes(fn):
1136 1150 pass
1137 1151 _getoutgoings(repo, other, missing, addfunc)
1138 1152
1139 1153 if not toupload:
1140 1154 ui.status(_('largefiles: no files to upload\n'))
1141 1155 else:
1142 1156 ui.status(_('largefiles to upload (%d entities):\n')
1143 1157 % (len(lfhashes)))
1144 1158 for file in sorted(toupload):
1145 1159 ui.status(lfutil.splitstandin(file) + '\n')
1146 1160 showhashes(file)
1147 1161 ui.status('\n')
1148 1162
1149 1163 def summaryremotehook(ui, repo, opts, changes):
1150 1164 largeopt = opts.get('large', False)
1151 1165 if changes is None:
1152 1166 if largeopt:
1153 1167 return (False, True) # only outgoing check is needed
1154 1168 else:
1155 1169 return (False, False)
1156 1170 elif largeopt:
1157 1171 url, branch, peer, outgoing = changes[1]
1158 1172 if peer is None:
1159 1173 # i18n: column positioning for "hg summary"
1160 1174 ui.status(_('largefiles: (no remote repo)\n'))
1161 1175 return
1162 1176
1163 1177 toupload = set()
1164 1178 lfhashes = set()
1165 1179 def addfunc(fn, lfhash):
1166 1180 toupload.add(fn)
1167 1181 lfhashes.add(lfhash)
1168 1182 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1169 1183
1170 1184 if not toupload:
1171 1185 # i18n: column positioning for "hg summary"
1172 1186 ui.status(_('largefiles: (no files to upload)\n'))
1173 1187 else:
1174 1188 # i18n: column positioning for "hg summary"
1175 1189 ui.status(_('largefiles: %d entities for %d files to upload\n')
1176 1190 % (len(lfhashes), len(toupload)))
1177 1191
1178 1192 def overridesummary(orig, ui, repo, *pats, **opts):
1179 1193 try:
1180 1194 repo.lfstatus = True
1181 1195 orig(ui, repo, *pats, **opts)
1182 1196 finally:
1183 1197 repo.lfstatus = False
1184 1198
1185 1199 def scmutiladdremove(orig, repo, matcher, prefix, opts=None, dry_run=None,
1186 1200 similarity=None):
1187 1201 if opts is None:
1188 1202 opts = {}
1189 1203 if not lfutil.islfilesrepo(repo):
1190 1204 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1191 1205 # Get the list of missing largefiles so we can remove them
1192 1206 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1193 1207 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1194 1208 False, False, False)
1195 1209
1196 1210 # Call into the normal remove code, but the removing of the standin, we want
1197 1211 # to have handled by original addremove. Monkey patching here makes sure
1198 1212 # we don't remove the standin in the largefiles code, preventing a very
1199 1213 # confused state later.
1200 1214 if s.deleted:
1201 1215 m = copy.copy(matcher)
1202 1216
1203 1217 # The m._files and m._map attributes are not changed to the deleted list
1204 1218 # because that affects the m.exact() test, which in turn governs whether
1205 1219 # or not the file name is printed, and how. Simply limit the original
1206 1220 # matches to those in the deleted status list.
1207 1221 matchfn = m.matchfn
1208 1222 m.matchfn = lambda f: f in s.deleted and matchfn(f)
1209 1223
1210 1224 removelargefiles(repo.ui, repo, True, m, **opts)
1211 1225 # Call into the normal add code, and any files that *should* be added as
1212 1226 # largefiles will be
1213 1227 added, bad = addlargefiles(repo.ui, repo, True, matcher, **opts)
1214 1228 # Now that we've handled largefiles, hand off to the original addremove
1215 1229 # function to take care of the rest. Make sure it doesn't do anything with
1216 1230 # largefiles by passing a matcher that will ignore them.
1217 1231 matcher = composenormalfilematcher(matcher, repo[None].manifest(), added)
1218 1232 return orig(repo, matcher, prefix, opts, dry_run, similarity)
1219 1233
1220 1234 # Calling purge with --all will cause the largefiles to be deleted.
1221 1235 # Override repo.status to prevent this from happening.
1222 1236 def overridepurge(orig, ui, repo, *dirs, **opts):
1223 1237 # XXX Monkey patching a repoview will not work. The assigned attribute will
1224 1238 # be set on the unfiltered repo, but we will only lookup attributes in the
1225 1239 # unfiltered repo if the lookup in the repoview object itself fails. As the
1226 1240 # monkey patched method exists on the repoview class the lookup will not
1227 1241 # fail. As a result, the original version will shadow the monkey patched
1228 1242 # one, defeating the monkey patch.
1229 1243 #
1230 1244 # As a work around we use an unfiltered repo here. We should do something
1231 1245 # cleaner instead.
1232 1246 repo = repo.unfiltered()
1233 1247 oldstatus = repo.status
1234 1248 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1235 1249 clean=False, unknown=False, listsubrepos=False):
1236 1250 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1237 1251 listsubrepos)
1238 1252 lfdirstate = lfutil.openlfdirstate(ui, repo)
1239 1253 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1240 1254 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1241 1255 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1242 1256 unknown, ignored, r.clean)
1243 1257 repo.status = overridestatus
1244 1258 orig(ui, repo, *dirs, **opts)
1245 1259 repo.status = oldstatus
1246 1260 def overriderollback(orig, ui, repo, **opts):
1247 1261 with repo.wlock():
1248 1262 before = repo.dirstate.parents()
1249 1263 orphans = set(f for f in repo.dirstate
1250 1264 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1251 1265 result = orig(ui, repo, **opts)
1252 1266 after = repo.dirstate.parents()
1253 1267 if before == after:
1254 1268 return result # no need to restore standins
1255 1269
1256 1270 pctx = repo['.']
1257 1271 for f in repo.dirstate:
1258 1272 if lfutil.isstandin(f):
1259 1273 orphans.discard(f)
1260 1274 if repo.dirstate[f] == 'r':
1261 1275 repo.wvfs.unlinkpath(f, ignoremissing=True)
1262 1276 elif f in pctx:
1263 1277 fctx = pctx[f]
1264 1278 repo.wwrite(f, fctx.data(), fctx.flags())
1265 1279 else:
1266 1280 # content of standin is not so important in 'a',
1267 1281 # 'm' or 'n' (coming from the 2nd parent) cases
1268 1282 lfutil.writestandin(repo, f, '', False)
1269 1283 for standin in orphans:
1270 1284 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1271 1285
1272 1286 lfdirstate = lfutil.openlfdirstate(ui, repo)
1273 1287 orphans = set(lfdirstate)
1274 1288 lfiles = lfutil.listlfiles(repo)
1275 1289 for file in lfiles:
1276 1290 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1277 1291 orphans.discard(file)
1278 1292 for lfile in orphans:
1279 1293 lfdirstate.drop(lfile)
1280 1294 lfdirstate.write()
1281 1295 return result
1282 1296
1283 1297 def overridetransplant(orig, ui, repo, *revs, **opts):
1284 1298 resuming = opts.get('continue')
1285 1299 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
1286 1300 repo._lfstatuswriters.append(lambda *msg, **opts: None)
1287 1301 try:
1288 1302 result = orig(ui, repo, *revs, **opts)
1289 1303 finally:
1290 1304 repo._lfstatuswriters.pop()
1291 1305 repo._lfcommithooks.pop()
1292 1306 return result
1293 1307
1294 1308 def overridecat(orig, ui, repo, file1, *pats, **opts):
1295 1309 ctx = scmutil.revsingle(repo, opts.get('rev'))
1296 1310 err = 1
1297 1311 notbad = set()
1298 1312 m = scmutil.match(ctx, (file1,) + pats, opts)
1299 1313 origmatchfn = m.matchfn
1300 1314 def lfmatchfn(f):
1301 1315 if origmatchfn(f):
1302 1316 return True
1303 1317 lf = lfutil.splitstandin(f)
1304 1318 if lf is None:
1305 1319 return False
1306 1320 notbad.add(lf)
1307 1321 return origmatchfn(lf)
1308 1322 m.matchfn = lfmatchfn
1309 1323 origbadfn = m.bad
1310 1324 def lfbadfn(f, msg):
1311 1325 if not f in notbad:
1312 1326 origbadfn(f, msg)
1313 1327 m.bad = lfbadfn
1314 1328
1315 1329 origvisitdirfn = m.visitdir
1316 1330 def lfvisitdirfn(dir):
1317 1331 if dir == lfutil.shortname:
1318 1332 return True
1319 1333 ret = origvisitdirfn(dir)
1320 1334 if ret:
1321 1335 return ret
1322 1336 lf = lfutil.splitstandin(dir)
1323 1337 if lf is None:
1324 1338 return False
1325 1339 return origvisitdirfn(lf)
1326 1340 m.visitdir = lfvisitdirfn
1327 1341
1328 1342 for f in ctx.walk(m):
1329 1343 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1330 1344 pathname=f)
1331 1345 lf = lfutil.splitstandin(f)
1332 1346 if lf is None or origmatchfn(f):
1333 1347 # duplicating unreachable code from commands.cat
1334 1348 data = ctx[f].data()
1335 1349 if opts.get('decode'):
1336 1350 data = repo.wwritedata(f, data)
1337 1351 fp.write(data)
1338 1352 else:
1339 1353 hash = lfutil.readstandin(repo, lf, ctx.rev())
1340 1354 if not lfutil.inusercache(repo.ui, hash):
1341 1355 store = storefactory._openstore(repo)
1342 1356 success, missing = store.get([(lf, hash)])
1343 1357 if len(success) != 1:
1344 1358 raise error.Abort(
1345 1359 _('largefile %s is not in cache and could not be '
1346 1360 'downloaded') % lf)
1347 1361 path = lfutil.usercachepath(repo.ui, hash)
1348 1362 fpin = open(path, "rb")
1349 1363 for chunk in util.filechunkiter(fpin, 128 * 1024):
1350 1364 fp.write(chunk)
1351 1365 fpin.close()
1352 1366 fp.close()
1353 1367 err = 0
1354 1368 return err
1355 1369
1356 1370 def mergeupdate(orig, repo, node, branchmerge, force,
1357 1371 *args, **kwargs):
1358 1372 matcher = kwargs.get('matcher', None)
1359 1373 # note if this is a partial update
1360 1374 partial = matcher and not matcher.always()
1361 1375 with repo.wlock():
1362 1376 # branch | | |
1363 1377 # merge | force | partial | action
1364 1378 # -------+-------+---------+--------------
1365 1379 # x | x | x | linear-merge
1366 1380 # o | x | x | branch-merge
1367 1381 # x | o | x | overwrite (as clean update)
1368 1382 # o | o | x | force-branch-merge (*1)
1369 1383 # x | x | o | (*)
1370 1384 # o | x | o | (*)
1371 1385 # x | o | o | overwrite (as revert)
1372 1386 # o | o | o | (*)
1373 1387 #
1374 1388 # (*) don't care
1375 1389 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1376 1390
1377 1391 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1378 1392 unsure, s = lfdirstate.status(match_.always(repo.root,
1379 1393 repo.getcwd()),
1380 1394 [], False, False, False)
1381 1395 pctx = repo['.']
1382 1396 for lfile in unsure + s.modified:
1383 1397 lfileabs = repo.wvfs.join(lfile)
1384 1398 if not repo.wvfs.exists(lfileabs):
1385 1399 continue
1386 1400 lfhash = lfutil.hashrepofile(repo, lfile)
1387 1401 standin = lfutil.standin(lfile)
1388 1402 lfutil.writestandin(repo, standin, lfhash,
1389 1403 lfutil.getexecutable(lfileabs))
1390 1404 if (standin in pctx and
1391 1405 lfhash == lfutil.readstandin(repo, lfile, '.')):
1392 1406 lfdirstate.normal(lfile)
1393 1407 for lfile in s.added:
1394 1408 lfutil.updatestandin(repo, lfutil.standin(lfile))
1395 1409 lfdirstate.write()
1396 1410
1397 1411 oldstandins = lfutil.getstandinsstate(repo)
1398 1412
1399 1413 result = orig(repo, node, branchmerge, force, *args, **kwargs)
1400 1414
1401 1415 newstandins = lfutil.getstandinsstate(repo)
1402 1416 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1403 1417 if branchmerge or force or partial:
1404 1418 filelist.extend(s.deleted + s.removed)
1405 1419
1406 1420 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1407 1421 normallookup=partial)
1408 1422
1409 1423 return result
1410 1424
1411 1425 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1412 1426 result = orig(repo, files, *args, **kwargs)
1413 1427
1414 1428 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1415 1429 if filelist:
1416 1430 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1417 1431 printmessage=False, normallookup=True)
1418 1432
1419 1433 return result
@@ -1,157 +1,156
1 1 #require test-repo
2 2
3 3 $ . "$TESTDIR/helpers-testrepo.sh"
4 4 $ cd "$TESTDIR"/..
5 5
6 6 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
7 7 hgext/fsmonitor/pywatchman/__init__.py not using absolute_import
8 8 hgext/fsmonitor/pywatchman/__init__.py requires print_function
9 9 hgext/fsmonitor/pywatchman/capabilities.py not using absolute_import
10 10 hgext/fsmonitor/pywatchman/pybser.py not using absolute_import
11 11 hgext/highlight/__init__.py not using absolute_import
12 12 hgext/highlight/highlight.py not using absolute_import
13 hgext/largefiles/overrides.py not using absolute_import
14 13 hgext/largefiles/proto.py not using absolute_import
15 14 hgext/largefiles/remotestore.py not using absolute_import
16 15 hgext/largefiles/reposetup.py not using absolute_import
17 16 hgext/largefiles/uisetup.py not using absolute_import
18 17 hgext/largefiles/wirestore.py not using absolute_import
19 18 hgext/share.py not using absolute_import
20 19 hgext/win32text.py not using absolute_import
21 20 i18n/check-translation.py not using absolute_import
22 21 i18n/polib.py not using absolute_import
23 22 setup.py not using absolute_import
24 23 tests/heredoctest.py requires print_function
25 24 tests/md5sum.py not using absolute_import
26 25 tests/readlink.py not using absolute_import
27 26 tests/run-tests.py not using absolute_import
28 27 tests/test-demandimport.py not using absolute_import
29 28
30 29 #if py3exe
31 30 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs $PYTHON3 contrib/check-py3-compat.py
32 31 doc/hgmanpage.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
33 32 hgext/automv.py: error importing module: <SyntaxError> invalid syntax (commands.py, line *) (line *) (glob)
34 33 hgext/blackbox.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
35 34 hgext/bugzilla.py: error importing module: <ImportError> No module named 'urlparse' (line *) (glob)
36 35 hgext/censor.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
37 36 hgext/chgserver.py: error importing module: <ImportError> No module named 'SocketServer' (line *) (glob)
38 37 hgext/children.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
39 38 hgext/churn.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
40 39 hgext/clonebundles.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
41 40 hgext/color.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
42 41 hgext/convert/bzr.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
43 42 hgext/convert/common.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
44 43 hgext/convert/convcmd.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
45 44 hgext/convert/cvs.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
46 45 hgext/convert/cvsps.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
47 46 hgext/convert/darcs.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
48 47 hgext/convert/filemap.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
49 48 hgext/convert/git.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
50 49 hgext/convert/gnuarch.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
51 50 hgext/convert/hg.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
52 51 hgext/convert/monotone.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
53 52 hgext/convert/p*.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *) (glob)
54 53 hgext/convert/subversion.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
55 54 hgext/convert/transport.py: error importing module: <ImportError> No module named 'svn.client' (line *) (glob)
56 55 hgext/eol.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
57 56 hgext/extdiff.py: error importing module: <SyntaxError> invalid syntax (archival.py, line *) (line *) (glob)
58 57 hgext/factotum.py: error importing: <ImportError> No module named 'rfc822' (error at __init__.py:*) (glob)
59 58 hgext/fetch.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
60 59 hgext/fsmonitor/watchmanclient.py: error importing module: <SystemError> Parent module 'hgext.fsmonitor' not loaded, cannot perform relative import (line *) (glob)
61 60 hgext/gpg.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
62 61 hgext/graphlog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
63 62 hgext/hgk.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
64 63 hgext/histedit.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
65 64 hgext/keyword.py: error importing: <ImportError> No module named 'BaseHTTPServer' (error at common.py:*) (glob)
66 65 hgext/largefiles/basestore.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
67 66 hgext/largefiles/lfcommands.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
68 67 hgext/largefiles/lfutil.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
69 68 hgext/largefiles/localstore.py: error importing module: <ImportError> No module named 'lfutil' (line *) (glob)
70 69 hgext/largefiles/overrides.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
71 70 hgext/largefiles/proto.py: error importing: <ImportError> No module named 'httplib' (error at httppeer.py:*) (glob)
72 71 hgext/largefiles/remotestore.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at wireproto.py:*) (glob)
73 72 hgext/largefiles/reposetup.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
74 73 hgext/largefiles/uisetup.py: error importing module: <SyntaxError> invalid syntax (archival.py, line *) (line *) (glob)
75 74 hgext/largefiles/wirestore.py: error importing module: <ImportError> No module named 'lfutil' (line *) (glob)
76 75 hgext/mq.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
77 76 hgext/notify.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
78 77 hgext/pager.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
79 78 hgext/patchbomb.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
80 79 hgext/purge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
81 80 hgext/rebase.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
82 81 hgext/record.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
83 82 hgext/relink.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
84 83 hgext/schemes.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
85 84 hgext/share.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
86 85 hgext/shelve.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
87 86 hgext/strip.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
88 87 hgext/transplant.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
89 88 mercurial/archival.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
90 89 mercurial/branchmap.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
91 90 mercurial/bundle*.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
92 91 mercurial/bundlerepo.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
93 92 mercurial/changegroup.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
94 93 mercurial/changelog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
95 94 mercurial/cmdutil.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
96 95 mercurial/commands.py: invalid syntax: invalid syntax (<unknown>, line *) (glob)
97 96 mercurial/commandserver.py: error importing module: <ImportError> No module named 'SocketServer' (line *) (glob)
98 97 mercurial/context.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
99 98 mercurial/copies.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
100 99 mercurial/crecord.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
101 100 mercurial/dirstate.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
102 101 mercurial/discovery.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
103 102 mercurial/dispatch.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
104 103 mercurial/exchange.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
105 104 mercurial/extensions.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
106 105 mercurial/filelog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
107 106 mercurial/filemerge.py: error importing: <ImportError> No module named 'cPickle' (error at formatter.py:*) (glob)
108 107 mercurial/fileset.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
109 108 mercurial/formatter.py: error importing module: <ImportError> No module named 'cPickle' (line *) (glob)
110 109 mercurial/graphmod.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
111 110 mercurial/help.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
112 111 mercurial/hg.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at bundlerepo.py:*) (glob)
113 112 mercurial/hgweb/common.py: error importing module: <ImportError> No module named 'BaseHTTPServer' (line *) (glob)
114 113 mercurial/hgweb/hgweb_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
115 114 mercurial/hgweb/hgwebdir_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
116 115 mercurial/hgweb/protocol.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
117 116 mercurial/hgweb/request.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
118 117 mercurial/hgweb/server.py: error importing module: <ImportError> No module named 'BaseHTTPServer' (line *) (glob)
119 118 mercurial/hgweb/webcommands.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
120 119 mercurial/hgweb/webutil.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
121 120 mercurial/hgweb/wsgicgi.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *) (glob)
122 121 mercurial/hook.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
123 122 mercurial/httpconnection.py: error importing: <ImportError> No module named 'rfc822' (error at __init__.py:*) (glob)
124 123 mercurial/httppeer.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
125 124 mercurial/keepalive.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
126 125 mercurial/localrepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
127 126 mercurial/mail.py: error importing module: <AttributeError> module 'email' has no attribute 'Header' (line *) (glob)
128 127 mercurial/manifest.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
129 128 mercurial/merge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
130 129 mercurial/namespaces.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
131 130 mercurial/patch.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
132 131 mercurial/pure/mpatch.py: error importing module: <ImportError> cannot import name 'pycompat' (line *) (glob)
133 132 mercurial/pure/parsers.py: error importing module: <ImportError> No module named 'mercurial.pure.node' (line *) (glob)
134 133 mercurial/repair.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
135 134 mercurial/revlog.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
136 135 mercurial/revset.py: error importing module: <AttributeError> 'dict' object has no attribute 'iteritems' (line *) (glob)
137 136 mercurial/scmutil.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
138 137 mercurial/scmwindows.py: error importing module: <ImportError> No module named '_winreg' (line *) (glob)
139 138 mercurial/simplemerge.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
140 139 mercurial/sshpeer.py: error importing: <SyntaxError> invalid syntax (bundle*.py, line *) (error at wireproto.py:*) (glob)
141 140 mercurial/sshserver.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
142 141 mercurial/statichttprepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
143 142 mercurial/store.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
144 143 mercurial/streamclone.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
145 144 mercurial/subrepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
146 145 mercurial/templatefilters.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
147 146 mercurial/templatekw.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
148 147 mercurial/templater.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
149 148 mercurial/ui.py: error importing: <ImportError> No module named 'cPickle' (error at formatter.py:*) (glob)
150 149 mercurial/unionrepo.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
151 150 mercurial/url.py: error importing module: <ImportError> No module named 'httplib' (line *) (glob)
152 151 mercurial/verify.py: error importing: <AttributeError> 'dict' object has no attribute 'iteritems' (error at revset.py:*) (glob)
153 152 mercurial/win*.py: error importing module: <ImportError> No module named 'msvcrt' (line *) (glob)
154 153 mercurial/windows.py: error importing module: <ImportError> No module named '_winreg' (line *) (glob)
155 154 mercurial/wireproto.py: error importing module: <SyntaxError> invalid syntax (bundle*.py, line *) (line *) (glob)
156 155
157 156 #endif
General Comments 0
You need to be logged in to leave comments. Login now