##// END OF EJS Templates
largefiles: implement addremove (issue3064)...
Na'Tosha Bard -
r15792:7cbba3ad default
parent child Browse files
Show More
@@ -20,6 +20,8 b' from hgext import rebase'
20 import lfutil
20 import lfutil
21 import lfcommands
21 import lfcommands
22
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
23 def installnormalfilesmatchfn(manifest):
25 def installnormalfilesmatchfn(manifest):
24 '''overrides scmutil.match so that the matcher it returns will ignore all
26 '''overrides scmutil.match so that the matcher it returns will ignore all
25 largefiles'''
27 largefiles'''
@@ -51,13 +53,7 b' def restorematchfn():'
51 restore matchfn to reverse'''
53 restore matchfn to reverse'''
52 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
53
55
54 # -- Wrappers: modify existing commands --------------------------------
56 def add_largefiles(ui, repo, *pats, **opts):
55
56 # Add works by going through the files that the user wanted to add and
57 # checking if they should be added as largefiles. Then it makes a new
58 # matcher which matches only the normal files and runs the original
59 # version of add.
60 def override_add(orig, ui, repo, *pats, **opts):
61 large = opts.pop('large', None)
57 large = opts.pop('large', None)
62 lfsize = lfutil.getminsize(
58 lfsize = lfutil.getminsize(
63 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
@@ -117,19 +113,9 b' def override_add(orig, ui, repo, *pats, '
117 if f in m.files()]
113 if f in m.files()]
118 finally:
114 finally:
119 wlock.release()
115 wlock.release()
120
116 return bad
121 installnormalfilesmatchfn(repo[None].manifest())
122 result = orig(ui, repo, *pats, **opts)
123 restorematchfn()
124
125 return (result == 1 or bad) and 1 or 0
126
117
127 def override_remove(orig, ui, repo, *pats, **opts):
118 def remove_largefiles(ui, repo, *pats, **opts):
128 manifest = repo[None].manifest()
129 installnormalfilesmatchfn(manifest)
130 orig(ui, repo, *pats, **opts)
131 restorematchfn()
132
133 after = opts.get('after')
119 after = opts.get('after')
134 if not pats and not after:
120 if not pats and not after:
135 raise util.Abort(_('no files specified'))
121 raise util.Abort(_('no files specified'))
@@ -139,6 +125,7 b' def override_remove(orig, ui, repo, *pat'
139 s = repo.status(match=m, clean=True)
125 s = repo.status(match=m, clean=True)
140 finally:
126 finally:
141 repo.lfstatus = False
127 repo.lfstatus = False
128 manifest = repo[None].manifest()
142 modified, added, deleted, clean = [[f for f in list
129 modified, added, deleted, clean = [[f for f in list
143 if lfutil.standin(f) in manifest]
130 if lfutil.standin(f) in manifest]
144 for list in [s[0], s[1], s[3], s[6]]]
131 for list in [s[0], s[1], s[3], s[6]]]
@@ -167,21 +154,48 b' def override_remove(orig, ui, repo, *pat'
167 lfdirstate = lfutil.openlfdirstate(ui, repo)
154 lfdirstate = lfutil.openlfdirstate(ui, repo)
168 for f in remove:
155 for f in remove:
169 if not after:
156 if not after:
170 os.unlink(repo.wjoin(f))
157 # If this is being called by addremove, notify the user that we
158 # are removing the file.
159 if getattr(repo, "_isaddremove", False):
160 ui.status(_('removing %s\n' % f))
161 if os.path.exists(repo.wjoin(f)):
162 os.unlink(repo.wjoin(f))
171 currentdir = os.path.split(f)[0]
163 currentdir = os.path.split(f)[0]
172 while currentdir and not os.listdir(repo.wjoin(currentdir)):
164 while currentdir and not os.listdir(repo.wjoin(currentdir)):
173 os.rmdir(repo.wjoin(currentdir))
165 os.rmdir(repo.wjoin(currentdir))
174 currentdir = os.path.split(currentdir)[0]
166 currentdir = os.path.split(currentdir)[0]
175 lfdirstate.remove(f)
167 lfdirstate.remove(f)
176 lfdirstate.write()
168 lfdirstate.write()
177
178 forget = [lfutil.standin(f) for f in forget]
169 forget = [lfutil.standin(f) for f in forget]
179 remove = [lfutil.standin(f) for f in remove]
170 remove = [lfutil.standin(f) for f in remove]
180 lfutil.repo_forget(repo, forget)
171 lfutil.repo_forget(repo, forget)
181 lfutil.repo_remove(repo, remove, unlink=True)
172 # If this is being called by addremove, let the original addremove
173 # function handle this.
174 if not getattr(repo, "_isaddremove", False):
175 lfutil.repo_remove(repo, remove, unlink=True)
182 finally:
176 finally:
183 wlock.release()
177 wlock.release()
184
178
179 # -- Wrappers: modify existing commands --------------------------------
180
181 # Add works by going through the files that the user wanted to add and
182 # checking if they should be added as largefiles. Then it makes a new
183 # matcher which matches only the normal files and runs the original
184 # version of add.
185 def override_add(orig, ui, repo, *pats, **opts):
186 bad = add_largefiles(ui, repo, *pats, **opts)
187 installnormalfilesmatchfn(repo[None].manifest())
188 result = orig(ui, repo, *pats, **opts)
189 restorematchfn()
190
191 return (result == 1 or bad) and 1 or 0
192
193 def override_remove(orig, ui, repo, *pats, **opts):
194 installnormalfilesmatchfn(repo[None].manifest())
195 orig(ui, repo, *pats, **opts)
196 restorematchfn()
197 remove_largefiles(ui, repo, *pats, **opts)
198
185 def override_status(orig, ui, repo, *pats, **opts):
199 def override_status(orig, ui, repo, *pats, **opts):
186 try:
200 try:
187 repo.lfstatus = True
201 repo.lfstatus = True
@@ -851,26 +865,29 b' def override_summary(orig, ui, repo, *pa'
851 ui.status(_('largefiles: %d to upload\n') % len(toupload))
865 ui.status(_('largefiles: %d to upload\n') % len(toupload))
852
866
853 def override_addremove(orig, ui, repo, *pats, **opts):
867 def override_addremove(orig, ui, repo, *pats, **opts):
854 # Check if the parent or child has largefiles; if so, disallow
868 # Get the list of missing largefiles so we can remove them
855 # addremove. If there is a symlink in the manifest then getting
869 lfdirstate = lfutil.openlfdirstate(ui, repo)
856 # the manifest throws an exception: catch it and let addremove
870 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
857 # deal with it.
871 False, False)
858 try:
872 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
859 manifesttip = set(repo['tip'].manifest())
860 except util.Abort:
861 manifesttip = set()
862 try:
863 manifestworking = set(repo[None].manifest())
864 except util.Abort:
865 manifestworking = set()
866
873
867 # Manifests are only iterable so turn them into sets then union
874 # Call into the normal remove code, but the removing of the standin, we want
868 for file in manifesttip.union(manifestworking):
875 # to have handled by original addremove. Monkey patching here makes sure
869 if file.startswith(lfutil.shortname):
876 # we don't remove the standin in the largefiles code, preventing a very
870 raise util.Abort(
877 # confused state later.
871 _('addremove cannot be run on a repo with largefiles'))
878 repo._isaddremove = True
872
879 remove_largefiles(ui, repo, *missing, **opts)
873 return orig(ui, repo, *pats, **opts)
880 repo._isaddremove = False
881 # Call into the normal add code, and any files that *should* be added as
882 # largefiles will be
883 add_largefiles(ui, repo, *pats, **opts)
884 # Now that we've handled largefiles, hand off to the original addremove
885 # function to take care of the rest. Make sure it doesn't do anything with
886 # largefiles by installing a matcher that will ignore them.
887 installnormalfilesmatchfn(repo[None].manifest())
888 result = orig(ui, repo, *pats, **opts)
889 restorematchfn()
890 return result
874
891
875 # Calling purge with --all will cause the largefiles to be deleted.
892 # Calling purge with --all will cause the largefiles to be deleted.
876 # Override repo.status to prevent this from happening.
893 # Override repo.status to prevent this from happening.
@@ -286,6 +286,20 b' dir after a purge.'
286 $ cat sub2/large7
286 $ cat sub2/large7
287 large7
287 large7
288
288
289 Test addremove: verify that files that should be added as largfiles are added as
290 such and that already-existing largfiles are not added as normal files by
291 accident.
292
293 $ rm normal3
294 $ rm sub/large4
295 $ echo "testing addremove with patterns" > testaddremove.dat
296 $ echo "normaladdremove" > normaladdremove
297 $ hg addremove
298 removing sub/large4
299 adding testaddremove.dat as a largefile
300 removing normal3
301 adding normaladdremove
302
289 Clone a largefiles repo.
303 Clone a largefiles repo.
290
304
291 $ hg clone . ../b
305 $ hg clone . ../b
General Comments 0
You need to be logged in to leave comments. Login now