hgext/largefiles/lfcommands.py
branchstable
changeset 20062 452f68738f69
parent 20061 5cb0ff40374d
child 20063 8a021cd38719
equal deleted inserted replaced
20061:5cb0ff40374d 20062:452f68738f69
   442             if printmessage:
   442             if printmessage:
   443                 ui.status(_('getting changed largefiles\n'))
   443                 ui.status(_('getting changed largefiles\n'))
   444             cachelfiles(ui, repo, None, lfiles)
   444             cachelfiles(ui, repo, None, lfiles)
   445 
   445 
   446         updated, removed = 0, 0
   446         updated, removed = 0, 0
   447         for f in lfiles:
   447         for lfile in lfiles:
   448             i = _updatelfile(repo, lfdirstate, f)
   448             # updates a single largefile and copies the state of its standin from
   449             if i:
   449             # the repository's dirstate to its state in the lfdirstate.
   450                 if i > 0:
   450             abslfile = repo.wjoin(lfile)
   451                     updated += i
   451             absstandin = repo.wjoin(lfutil.standin(lfile))
       
   452             if os.path.exists(absstandin):
       
   453                 if (os.path.exists(absstandin + '.orig') and
       
   454                     os.path.exists(abslfile)):
       
   455                     shutil.copyfile(abslfile, abslfile + '.orig')
       
   456                 update1 = 0
       
   457                 expecthash = lfutil.readstandin(repo, lfile)
       
   458                 if (expecthash != '' and
       
   459                     (not os.path.exists(abslfile) or
       
   460                      expecthash != lfutil.hashfile(abslfile))):
       
   461                     if not lfutil.copyfromcache(repo, expecthash, lfile):
       
   462                         # use normallookup() to allocate entry in largefiles
       
   463                         # dirstate, because lack of it misleads
       
   464                         # lfilesrepo.status() into recognition that such cache
       
   465                         # missing files are REMOVED.
       
   466                         if lfile not in repo[None]: # not switched to normal
       
   467                             util.unlinkpath(abslfile, ignoremissing=True)
       
   468                         lfdirstate.normallookup(lfile)
       
   469                         continue # don't try to set the mode
       
   470                     else:
       
   471                         # Synchronize largefile dirstate to the last modified
       
   472                         # time of the file
       
   473                         lfdirstate.normal(lfile)
       
   474                     update1 = 1
       
   475                 mode = os.stat(absstandin).st_mode
       
   476                 if mode != os.stat(abslfile).st_mode:
       
   477                     os.chmod(abslfile, mode)
       
   478                     update1 = 1
       
   479                 updated += update1
       
   480             else:
       
   481                 # Remove lfiles for which the standin is deleted, unless the
       
   482                 # lfile is added to the repository again. This happens when a
       
   483                 # largefile is converted back to a normal file: the standin
       
   484                 # disappears, but a new (normal) file appears as the lfile.
       
   485                 if (os.path.exists(abslfile) and
       
   486                     repo.dirstate.normalize(lfile) not in repo[None]):
       
   487                     util.unlinkpath(abslfile)
       
   488                     removed += 1
       
   489             state = repo.dirstate[lfutil.standin(lfile)]
       
   490             if state == 'n':
       
   491                 # When rebasing, we need to synchronize the standin and the
       
   492                 # largefile, because otherwise the largefile will get reverted.
       
   493                 # But for commit's sake, we have to mark the file as unclean.
       
   494                 if getattr(repo, "_isrebasing", False):
       
   495                     lfdirstate.normallookup(lfile)
   452                 else:
   496                 else:
   453                     removed -= i
   497                     lfdirstate.normal(lfile)
       
   498             elif state == 'r':
       
   499                 lfdirstate.remove(lfile)
       
   500             elif state == 'a':
       
   501                 lfdirstate.add(lfile)
       
   502             elif state == '?':
       
   503                 lfdirstate.drop(lfile)
   454 
   504 
   455         lfdirstate.write()
   505         lfdirstate.write()
   456         if printmessage and lfiles:
   506         if printmessage and lfiles:
   457             ui.status(_('%d largefiles updated, %d removed\n') % (updated,
   507             ui.status(_('%d largefiles updated, %d removed\n') % (updated,
   458                 removed))
   508                 removed))
   459     finally:
   509     finally:
   460         wlock.release()
   510         wlock.release()
   461 
       
   462 def _updatelfile(repo, lfdirstate, lfile):
       
   463     '''updates a single largefile and copies the state of its standin from
       
   464     the repository's dirstate to its state in the lfdirstate.
       
   465 
       
   466     returns 1 if the file was modified, -1 if the file was removed, 0 if the
       
   467     file was unchanged, and None if the needed largefile was missing from the
       
   468     cache.'''
       
   469     ret = 0
       
   470     abslfile = repo.wjoin(lfile)
       
   471     absstandin = repo.wjoin(lfutil.standin(lfile))
       
   472     if os.path.exists(absstandin):
       
   473         if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile):
       
   474             shutil.copyfile(abslfile, abslfile + '.orig')
       
   475         expecthash = lfutil.readstandin(repo, lfile)
       
   476         if (expecthash != '' and
       
   477             (not os.path.exists(abslfile) or
       
   478              expecthash != lfutil.hashfile(abslfile))):
       
   479             if not lfutil.copyfromcache(repo, expecthash, lfile):
       
   480                 # use normallookup() to allocate entry in largefiles dirstate,
       
   481                 # because lack of it misleads lfilesrepo.status() into
       
   482                 # recognition that such cache missing files are REMOVED.
       
   483                 if lfile not in repo[None]: # not switched to normal file
       
   484                     util.unlinkpath(abslfile, ignoremissing=True)
       
   485                 lfdirstate.normallookup(lfile)
       
   486                 return None # don't try to set the mode
       
   487             else:
       
   488                 # Synchronize largefile dirstate to the last modified time of
       
   489                 # the file
       
   490                 lfdirstate.normal(lfile)
       
   491             ret = 1
       
   492         mode = os.stat(absstandin).st_mode
       
   493         if mode != os.stat(abslfile).st_mode:
       
   494             os.chmod(abslfile, mode)
       
   495             ret = 1
       
   496     else:
       
   497         # Remove lfiles for which the standin is deleted, unless the
       
   498         # lfile is added to the repository again. This happens when a
       
   499         # largefile is converted back to a normal file: the standin
       
   500         # disappears, but a new (normal) file appears as the lfile.
       
   501         if (os.path.exists(abslfile) and
       
   502             repo.dirstate.normalize(lfile) not in repo[None]):
       
   503             util.unlinkpath(abslfile)
       
   504             ret = -1
       
   505     state = repo.dirstate[lfutil.standin(lfile)]
       
   506     if state == 'n':
       
   507         # When rebasing, we need to synchronize the standin and the largefile,
       
   508         # because otherwise the largefile will get reverted.  But for commit's
       
   509         # sake, we have to mark the file as unclean.
       
   510         if getattr(repo, "_isrebasing", False):
       
   511             lfdirstate.normallookup(lfile)
       
   512         else:
       
   513             lfdirstate.normal(lfile)
       
   514     elif state == 'r':
       
   515         lfdirstate.remove(lfile)
       
   516     elif state == 'a':
       
   517         lfdirstate.add(lfile)
       
   518     elif state == '?':
       
   519         lfdirstate.drop(lfile)
       
   520     return ret
       
   521 
   511 
   522 def lfpull(ui, repo, source="default", **opts):
   512 def lfpull(ui, repo, source="default", **opts):
   523     """pull largefiles for the specified revisions from the specified source
   513     """pull largefiles for the specified revisions from the specified source
   524 
   514 
   525     Pull largefiles that are referenced from local changesets but missing
   515     Pull largefiles that are referenced from local changesets but missing