Mercurial > hg
annotate hgext/largefiles/overrides.py @ 15323:19368c54a774 stable
largefiles: remove all uses of os.path.relpath for 2.4 compatibility
author | Benjamin Pollack <benjamin@bitquabit.com> |
---|---|
date | Thu, 20 Oct 2011 17:40:25 -0400 |
parents | 94527d67f3da |
children | b4ea79f88268 |
rev | line source |
---|---|
15168 | 1 # Copyright 2009-2010 Gregory P. Ward |
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated | |
3 # Copyright 2010-2011 Fog Creek Software | |
4 # Copyright 2010-2011 Unity Technologies | |
5 # | |
6 # This software may be used and distributed according to the terms of the | |
7 # GNU General Public License version 2 or any later version. | |
8 | |
9 '''Overridden Mercurial commands and functions for the largefiles extension''' | |
10 | |
11 import os | |
12 import copy | |
13 | |
15305 | 14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \ |
15 node, archival, error, merge | |
15168 | 16 from mercurial.i18n import _ |
17 from mercurial.node import hex | |
18 from hgext import rebase | |
19 | |
20 import lfutil | |
21 import lfcommands | |
22 | |
23 def installnormalfilesmatchfn(manifest): | |
24 '''overrides scmutil.match so that the matcher it returns will ignore all | |
25 largefiles''' | |
26 oldmatch = None # for the closure | |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
27 def override_match(ctx, pats=[], opts={}, globbed=False, |
15168 | 28 default='relpath'): |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
29 match = oldmatch(ctx, pats, opts, globbed, default) |
15168 | 30 m = copy.copy(match) |
31 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in | |
32 manifest) | |
33 m._files = filter(notlfile, m._files) | |
34 m._fmap = set(m._files) | |
35 orig_matchfn = m.matchfn | |
36 m.matchfn = lambda f: notlfile(f) and orig_matchfn(f) or None | |
37 return m | |
38 oldmatch = installmatchfn(override_match) | |
39 | |
40 def installmatchfn(f): | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
41 oldmatch = scmutil.match |
15168 | 42 setattr(f, 'oldmatch', oldmatch) |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
43 scmutil.match = f |
15168 | 44 return oldmatch |
45 | |
46 def restorematchfn(): | |
47 '''restores scmutil.match to what it was before installnormalfilesmatchfn | |
48 was called. no-op if scmutil.match is its original function. | |
49 | |
50 Note that n calls to installnormalfilesmatchfn will require n calls to | |
51 restore matchfn to reverse''' | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
52 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match) |
15168 | 53 |
54 # -- Wrappers: modify existing commands -------------------------------- | |
55 | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
56 # Add works by going through the files that the user wanted to add and |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
57 # checking if they should be added as largefiles. Then it makes a new |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
58 # matcher which matches only the normal files and runs the original |
15168 | 59 # version of add. |
60 def override_add(orig, ui, repo, *pats, **opts): | |
61 large = opts.pop('large', None) | |
15227
a7686abf73a6
largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
62 lfsize = lfutil.getminsize( |
a7686abf73a6
largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
63 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None)) |
15168 | 64 |
65 lfmatcher = None | |
66 if os.path.exists(repo.wjoin(lfutil.shortname)): | |
15229
89e19ca2a90e
largefiles: use ui.configlist() to split largefiles.patterns
Greg Ward <greg@gerg.ca>
parents:
15227
diff
changeset
|
67 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[]) |
15168 | 68 if lfpats: |
69 lfmatcher = match_.match(repo.root, '', list(lfpats)) | |
70 | |
71 lfnames = [] | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
72 m = scmutil.match(repo[None], pats, opts) |
15168 | 73 m.bad = lambda x, y: None |
74 wctx = repo[None] | |
75 for f in repo.walk(m): | |
76 exact = m.exact(f) | |
77 lfile = lfutil.standin(f) in wctx | |
78 nfile = f in wctx | |
79 exists = lfile or nfile | |
80 | |
81 # Don't warn the user when they attempt to add a normal tracked file. | |
82 # The normal add code will do that for us. | |
83 if exact and exists: | |
84 if lfile: | |
85 ui.warn(_('%s already a largefile\n') % f) | |
86 continue | |
87 | |
88 if exact or not exists: | |
15255
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
89 abovemin = (lfsize and |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
90 os.path.getsize(repo.wjoin(f)) >= lfsize * 1024 * 1024) |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
91 if large or abovemin or (lfmatcher and lfmatcher(f)): |
15168 | 92 lfnames.append(f) |
93 if ui.verbose or not exact: | |
94 ui.status(_('adding %s as a largefile\n') % m.rel(f)) | |
95 | |
96 bad = [] | |
97 standins = [] | |
98 | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
99 # Need to lock, otherwise there could be a race condition between |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
100 # when standins are created and added to the repo. |
15168 | 101 wlock = repo.wlock() |
102 try: | |
103 if not opts.get('dry_run'): | |
104 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
105 for f in lfnames: | |
106 standinname = lfutil.standin(f) | |
107 lfutil.writestandin(repo, standinname, hash='', | |
108 executable=lfutil.getexecutable(repo.wjoin(f))) | |
109 standins.append(standinname) | |
110 if lfdirstate[f] == 'r': | |
111 lfdirstate.normallookup(f) | |
112 else: | |
113 lfdirstate.add(f) | |
114 lfdirstate.write() | |
15255
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
115 bad += [lfutil.splitstandin(f) |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
116 for f in lfutil.repo_add(repo, standins) |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
117 if f in m.files()] |
15168 | 118 finally: |
119 wlock.release() | |
120 | |
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 | |
127 def override_remove(orig, ui, repo, *pats, **opts): | |
128 manifest = repo[None].manifest() | |
129 installnormalfilesmatchfn(manifest) | |
130 orig(ui, repo, *pats, **opts) | |
131 restorematchfn() | |
132 | |
133 after, force = opts.get('after'), opts.get('force') | |
134 if not pats and not after: | |
135 raise util.Abort(_('no files specified')) | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
136 m = scmutil.match(repo[None], pats, opts) |
15168 | 137 try: |
138 repo.lfstatus = True | |
139 s = repo.status(match=m, clean=True) | |
140 finally: | |
141 repo.lfstatus = False | |
15255
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
142 modified, added, deleted, clean = [[f for f in list |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
143 if lfutil.standin(f) in manifest] |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
144 for list in [s[0], s[1], s[3], s[6]]] |
15168 | 145 |
146 def warn(files, reason): | |
147 for f in files: | |
15294
db7b09e689f1
largefiles: make parameter more i18n-friendly
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
15279
diff
changeset
|
148 ui.warn(_('not removing %s: %s (use -f to force removal)\n') |
15168 | 149 % (m.rel(f), reason)) |
150 | |
151 if force: | |
152 remove, forget = modified + deleted + clean, added | |
153 elif after: | |
154 remove, forget = deleted, [] | |
15294
db7b09e689f1
largefiles: make parameter more i18n-friendly
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
15279
diff
changeset
|
155 warn(modified + added + clean, _('file still exists')) |
15168 | 156 else: |
157 remove, forget = deleted + clean, [] | |
15294
db7b09e689f1
largefiles: make parameter more i18n-friendly
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
15279
diff
changeset
|
158 warn(modified, _('file is modified')) |
db7b09e689f1
largefiles: make parameter more i18n-friendly
Wagner Bruna <wbruna@softwareexpress.com.br>
parents:
15279
diff
changeset
|
159 warn(added, _('file has been marked for add')) |
15168 | 160 |
161 for f in sorted(remove + forget): | |
162 if ui.verbose or not m.exact(f): | |
163 ui.status(_('removing %s\n') % m.rel(f)) | |
164 | |
165 # Need to lock because standin files are deleted then removed from the | |
166 # repository and we could race inbetween. | |
167 wlock = repo.wlock() | |
168 try: | |
169 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
170 for f in remove: | |
171 if not after: | |
172 os.unlink(repo.wjoin(f)) | |
173 currentdir = os.path.split(f)[0] | |
174 while currentdir and not os.listdir(repo.wjoin(currentdir)): | |
175 os.rmdir(repo.wjoin(currentdir)) | |
176 currentdir = os.path.split(currentdir)[0] | |
177 lfdirstate.remove(f) | |
178 lfdirstate.write() | |
179 | |
180 forget = [lfutil.standin(f) for f in forget] | |
181 remove = [lfutil.standin(f) for f in remove] | |
182 lfutil.repo_forget(repo, forget) | |
183 lfutil.repo_remove(repo, remove, unlink=True) | |
184 finally: | |
185 wlock.release() | |
186 | |
187 def override_status(orig, ui, repo, *pats, **opts): | |
188 try: | |
189 repo.lfstatus = True | |
190 return orig(ui, repo, *pats, **opts) | |
191 finally: | |
192 repo.lfstatus = False | |
193 | |
194 def override_log(orig, ui, repo, *pats, **opts): | |
195 try: | |
196 repo.lfstatus = True | |
197 orig(ui, repo, *pats, **opts) | |
198 finally: | |
199 repo.lfstatus = False | |
200 | |
201 def override_verify(orig, ui, repo, *pats, **opts): | |
202 large = opts.pop('large', False) | |
203 all = opts.pop('lfa', False) | |
204 contents = opts.pop('lfc', False) | |
205 | |
206 result = orig(ui, repo, *pats, **opts) | |
207 if large: | |
208 result = result or lfcommands.verifylfiles(ui, repo, all, contents) | |
209 return result | |
210 | |
211 # Override needs to refresh standins so that update's normal merge | |
212 # will go through properly. Then the other update hook (overriding repo.update) | |
213 # will get the new files. Filemerge is also overriden so that the merge | |
214 # will merge standins correctly. | |
215 def override_update(orig, ui, repo, *pats, **opts): | |
216 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
217 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False, | |
218 False, False) | |
219 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s | |
220 | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
221 # Need to lock between the standins getting updated and their |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
222 # largefiles getting updated |
15168 | 223 wlock = repo.wlock() |
224 try: | |
225 if opts['check']: | |
226 mod = len(modified) > 0 | |
227 for lfile in unsure: | |
228 standin = lfutil.standin(lfile) | |
229 if repo['.'][standin].data().strip() != \ | |
230 lfutil.hashfile(repo.wjoin(lfile)): | |
231 mod = True | |
232 else: | |
233 lfdirstate.normal(lfile) | |
234 lfdirstate.write() | |
235 if mod: | |
236 raise util.Abort(_('uncommitted local changes')) | |
237 # XXX handle removed differently | |
238 if not opts['clean']: | |
239 for lfile in unsure + modified + added: | |
240 lfutil.updatestandin(repo, lfutil.standin(lfile)) | |
241 finally: | |
242 wlock.release() | |
243 return orig(ui, repo, *pats, **opts) | |
244 | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
245 # Override filemerge to prompt the user about how they wish to merge |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
246 # largefiles. This will handle identical edits, and copy/rename + |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
247 # edit without prompting the user. |
15168 | 248 def override_filemerge(origfn, repo, mynode, orig, fcd, fco, fca): |
249 # Use better variable names here. Because this is a wrapper we cannot | |
250 # change the variable names in the function declaration. | |
251 fcdest, fcother, fcancestor = fcd, fco, fca | |
252 if not lfutil.isstandin(orig): | |
253 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor) | |
254 else: | |
255 if not fcother.cmp(fcdest): # files identical? | |
256 return None | |
257 | |
258 # backwards, use working dir parent as ancestor | |
259 if fcancestor == fcother: | |
260 fcancestor = fcdest.parents()[0] | |
261 | |
262 if orig != fcother.path(): | |
263 repo.ui.status(_('merging %s and %s to %s\n') | |
264 % (lfutil.splitstandin(orig), | |
265 lfutil.splitstandin(fcother.path()), | |
266 lfutil.splitstandin(fcdest.path()))) | |
267 else: | |
268 repo.ui.status(_('merging %s\n') | |
269 % lfutil.splitstandin(fcdest.path())) | |
270 | |
271 if fcancestor.path() != fcother.path() and fcother.data() == \ | |
272 fcancestor.data(): | |
273 return 0 | |
274 if fcancestor.path() != fcdest.path() and fcdest.data() == \ | |
275 fcancestor.data(): | |
276 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags()) | |
277 return 0 | |
278 | |
279 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n' | |
280 'keep (l)ocal or take (o)ther?') % | |
281 lfutil.splitstandin(orig), | |
282 (_('&Local'), _('&Other')), 0) == 0: | |
283 return 0 | |
284 else: | |
285 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags()) | |
286 return 0 | |
287 | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
288 # Copy first changes the matchers to match standins instead of |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
289 # largefiles. Then it overrides util.copyfile in that function it |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
290 # checks if the destination largefile already exists. It also keeps a |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
291 # list of copied files so that the largefiles can be copied and the |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
292 # dirstate updated. |
15168 | 293 def override_copy(orig, ui, repo, pats, opts, rename=False): |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15229
diff
changeset
|
294 # doesn't remove largefile on rename |
15168 | 295 if len(pats) < 2: |
296 # this isn't legal, let the original function deal with it | |
297 return orig(ui, repo, pats, opts, rename) | |
298 | |
299 def makestandin(relpath): | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
300 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath) |
15323
19368c54a774
largefiles: remove all uses of os.path.relpath for 2.4 compatibility
Benjamin Pollack <benjamin@bitquabit.com>
parents:
15306
diff
changeset
|
301 return os.path.join(repo.wjoin(lfutil.standin(path))) |
15168 | 302 |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
303 fullpats = scmutil.expandpats(pats) |
15168 | 304 dest = fullpats[-1] |
305 | |
306 if os.path.isdir(dest): | |
307 if not os.path.isdir(makestandin(dest)): | |
308 os.makedirs(makestandin(dest)) | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
309 # This could copy both lfiles and normal files in one command, |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
310 # but we don't want to do that. First replace their matcher to |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
311 # only match normal files and run it, then replace it to just |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
312 # match largefiles and run it again. |
15168 | 313 nonormalfiles = False |
314 nolfiles = False | |
315 try: | |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
316 try: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
317 installnormalfilesmatchfn(repo[None].manifest()) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
318 result = orig(ui, repo, pats, opts, rename) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
319 except util.Abort, e: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
320 if str(e) != 'no files to copy': |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
321 raise e |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
322 else: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
323 nonormalfiles = True |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
324 result = 0 |
15168 | 325 finally: |
326 restorematchfn() | |
327 | |
328 # The first rename can cause our current working directory to be removed. | |
329 # In that case there is nothing left to copy/rename so just quit. | |
330 try: | |
331 repo.getcwd() | |
332 except OSError: | |
333 return result | |
334 | |
335 try: | |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
336 try: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
337 # When we call orig below it creates the standins but we don't add them |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
338 # to the dir state until later so lock during that time. |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
339 wlock = repo.wlock() |
15168 | 340 |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
341 manifest = repo[None].manifest() |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
342 oldmatch = None # for the closure |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
343 def override_match(ctx, pats=[], opts={}, globbed=False, |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
344 default='relpath'): |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
345 newpats = [] |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
346 # The patterns were previously mangled to add the standin |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
347 # directory; we need to remove that now |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
348 for pat in pats: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
349 if match_.patkind(pat) is None and lfutil.shortname in pat: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
350 newpats.append(pat.replace(lfutil.shortname, '')) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
351 else: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
352 newpats.append(pat) |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
353 match = oldmatch(ctx, newpats, opts, globbed, default) |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
354 m = copy.copy(match) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
355 lfile = lambda f: lfutil.standin(f) in manifest |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
356 m._files = [lfutil.standin(f) for f in m._files if lfile(f)] |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
357 m._fmap = set(m._files) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
358 orig_matchfn = m.matchfn |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
359 m.matchfn = lambda f: (lfutil.isstandin(f) and |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
360 lfile(lfutil.splitstandin(f)) and |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
361 orig_matchfn(lfutil.splitstandin(f)) or |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
362 None) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
363 return m |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
364 oldmatch = installmatchfn(override_match) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
365 listpats = [] |
15168 | 366 for pat in pats: |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
367 if match_.patkind(pat) is not None: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
368 listpats.append(pat) |
15168 | 369 else: |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
370 listpats.append(makestandin(pat)) |
15168 | 371 |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
372 try: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
373 origcopyfile = util.copyfile |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
374 copiedfiles = [] |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
375 def override_copyfile(src, dest): |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
376 if lfutil.shortname in src and lfutil.shortname in dest: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
377 destlfile = dest.replace(lfutil.shortname, '') |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
378 if not opts['force'] and os.path.exists(destlfile): |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
379 raise IOError('', |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
380 _('destination largefile already exists')) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
381 copiedfiles.append((src, dest)) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
382 origcopyfile(src, dest) |
15168 | 383 |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
384 util.copyfile = override_copyfile |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
385 result += orig(ui, repo, listpats, opts, rename) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
386 finally: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
387 util.copyfile = origcopyfile |
15168 | 388 |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
389 lfdirstate = lfutil.openlfdirstate(ui, repo) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
390 for (src, dest) in copiedfiles: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
391 if lfutil.shortname in src and lfutil.shortname in dest: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
392 srclfile = src.replace(lfutil.shortname, '') |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
393 destlfile = dest.replace(lfutil.shortname, '') |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
394 destlfiledir = os.path.dirname(destlfile) or '.' |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
395 if not os.path.isdir(destlfiledir): |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
396 os.makedirs(destlfiledir) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
397 if rename: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
398 os.rename(srclfile, destlfile) |
15323
19368c54a774
largefiles: remove all uses of os.path.relpath for 2.4 compatibility
Benjamin Pollack <benjamin@bitquabit.com>
parents:
15306
diff
changeset
|
399 lfdirstate.remove(repo.wjoin(srclfile)) |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
400 else: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
401 util.copyfile(srclfile, destlfile) |
15323
19368c54a774
largefiles: remove all uses of os.path.relpath for 2.4 compatibility
Benjamin Pollack <benjamin@bitquabit.com>
parents:
15306
diff
changeset
|
402 lfdirstate.add(repo.wjoin(destlfile)) |
15279
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
403 lfdirstate.write() |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
404 except util.Abort, e: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
405 if str(e) != 'no files to copy': |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
406 raise e |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
407 else: |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
408 nolfiles = True |
15168 | 409 finally: |
410 restorematchfn() | |
411 wlock.release() | |
412 | |
413 if nolfiles and nonormalfiles: | |
414 raise util.Abort(_('no files to copy')) | |
415 | |
416 return result | |
417 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
418 # When the user calls revert, we have to be careful to not revert any |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
419 # changes to other largefiles accidentally. This means we have to keep |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
420 # track of the largefiles that are being reverted so we only pull down |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
421 # the necessary largefiles. |
15168 | 422 # |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
423 # Standins are only updated (to match the hash of largefiles) before |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
424 # commits. Update the standins then run the original revert, changing |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
425 # the matcher to hit standins instead of largefiles. Based on the |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
426 # resulting standins update the largefiles. Then return the standins |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
427 # to their proper state |
15168 | 428 def override_revert(orig, ui, repo, *pats, **opts): |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
429 # Because we put the standins in a bad state (by updating them) |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
430 # and then return them to a correct state we need to lock to |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
431 # prevent others from changing them in their incorrect state. |
15168 | 432 wlock = repo.wlock() |
433 try: | |
434 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
435 (modified, added, removed, missing, unknown, ignored, clean) = \ | |
436 lfutil.lfdirstate_status(lfdirstate, repo, repo['.'].rev()) | |
437 for lfile in modified: | |
438 lfutil.updatestandin(repo, lfutil.standin(lfile)) | |
439 | |
440 try: | |
441 ctx = repo[opts.get('rev')] | |
442 oldmatch = None # for the closure | |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
443 def override_match(ctx, pats=[], opts={}, globbed=False, |
15168 | 444 default='relpath'): |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
445 match = oldmatch(ctx, pats, opts, globbed, default) |
15168 | 446 m = copy.copy(match) |
447 def tostandin(f): | |
15306
94527d67f3da
largefiles: fix some badly named function parameters
Greg Ward <greg@gerg.ca>
parents:
15305
diff
changeset
|
448 if lfutil.standin(f) in ctx or lfutil.standin(f) in ctx: |
15168 | 449 return lfutil.standin(f) |
450 elif lfutil.standin(f) in repo[None]: | |
451 return None | |
452 return f | |
453 m._files = [tostandin(f) for f in m._files] | |
454 m._files = [f for f in m._files if f is not None] | |
455 m._fmap = set(m._files) | |
456 orig_matchfn = m.matchfn | |
457 def matchfn(f): | |
458 if lfutil.isstandin(f): | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
459 # We need to keep track of what largefiles are being |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
460 # matched so we know which ones to update later -- |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
461 # otherwise we accidentally revert changes to other |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
462 # largefiles. This is repo-specific, so duckpunch the |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
463 # repo object to keep the list of largefiles for us |
15168 | 464 # later. |
465 if orig_matchfn(lfutil.splitstandin(f)) and \ | |
466 (f in repo[None] or f in ctx): | |
467 lfileslist = getattr(repo, '_lfilestoupdate', []) | |
468 lfileslist.append(lfutil.splitstandin(f)) | |
469 repo._lfilestoupdate = lfileslist | |
470 return True | |
471 else: | |
472 return False | |
473 return orig_matchfn(f) | |
474 m.matchfn = matchfn | |
475 return m | |
476 oldmatch = installmatchfn(override_match) | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
477 scmutil.match |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
478 matches = override_match(repo[None], pats, opts) |
15168 | 479 orig(ui, repo, *pats, **opts) |
480 finally: | |
481 restorematchfn() | |
482 lfileslist = getattr(repo, '_lfilestoupdate', []) | |
15170
c1a4a3220711
largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents:
15169
diff
changeset
|
483 lfcommands.updatelfiles(ui, repo, filelist=lfileslist, |
c1a4a3220711
largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents:
15169
diff
changeset
|
484 printmessage=False) |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
485 |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
486 # empty out the largefiles list so we start fresh next time |
15168 | 487 repo._lfilestoupdate = [] |
488 for lfile in modified: | |
489 if lfile in lfileslist: | |
490 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\ | |
491 in repo['.']: | |
492 lfutil.writestandin(repo, lfutil.standin(lfile), | |
493 repo['.'][lfile].data().strip(), | |
494 'x' in repo['.'][lfile].flags()) | |
495 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
496 for lfile in added: | |
497 standin = lfutil.standin(lfile) | |
498 if standin not in ctx and (standin in matches or opts.get('all')): | |
499 if lfile in lfdirstate: | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
500 lfdirstate.drop(lfile) |
15168 | 501 util.unlinkpath(repo.wjoin(standin)) |
502 lfdirstate.write() | |
503 finally: | |
504 wlock.release() | |
505 | |
506 def hg_update(orig, repo, node): | |
507 result = orig(repo, node) | |
508 # XXX check if it worked first | |
509 lfcommands.updatelfiles(repo.ui, repo) | |
510 return result | |
511 | |
512 def hg_clean(orig, repo, node, show_stats=True): | |
513 result = orig(repo, node, show_stats) | |
514 lfcommands.updatelfiles(repo.ui, repo) | |
515 return result | |
516 | |
517 def hg_merge(orig, repo, node, force=None, remind=True): | |
518 result = orig(repo, node, force, remind) | |
519 lfcommands.updatelfiles(repo.ui, repo) | |
520 return result | |
521 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
522 # When we rebase a repository with remotely changed largefiles, we need to |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
523 # take some extra care so that the largefiles are correctly updated in the |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
524 # working copy |
15168 | 525 def override_pull(orig, ui, repo, source=None, **opts): |
526 if opts.get('rebase', False): | |
527 repo._isrebasing = True | |
528 try: | |
529 if opts.get('update'): | |
530 del opts['update'] | |
531 ui.debug('--update and --rebase are not compatible, ignoring ' | |
532 'the update flag\n') | |
533 del opts['rebase'] | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
534 cmdutil.bailifchanged(repo) |
15168 | 535 revsprepull = len(repo) |
536 origpostincoming = commands.postincoming | |
537 def _dummy(*args, **kwargs): | |
538 pass | |
539 commands.postincoming = _dummy | |
540 repo.lfpullsource = source | |
541 if not source: | |
542 source = 'default' | |
543 try: | |
544 result = commands.pull(ui, repo, source, **opts) | |
545 finally: | |
546 commands.postincoming = origpostincoming | |
547 revspostpull = len(repo) | |
548 if revspostpull > revsprepull: | |
549 result = result or rebase.rebase(ui, repo) | |
550 finally: | |
551 repo._isrebasing = False | |
552 else: | |
553 repo.lfpullsource = source | |
554 if not source: | |
555 source = 'default' | |
556 result = orig(ui, repo, source, **opts) | |
557 return result | |
558 | |
559 def override_rebase(orig, ui, repo, **opts): | |
560 repo._isrebasing = True | |
561 try: | |
562 orig(ui, repo, **opts) | |
563 finally: | |
564 repo._isrebasing = False | |
565 | |
566 def override_archive(orig, repo, dest, node, kind, decode=True, matchfn=None, | |
567 prefix=None, mtime=None, subrepos=None): | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
568 # No need to lock because we are only reading history and |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
569 # largefile caches, neither of which are modified. |
15168 | 570 lfcommands.cachelfiles(repo.ui, repo, node) |
571 | |
572 if kind not in archival.archivers: | |
573 raise util.Abort(_("unknown archive type '%s'") % kind) | |
574 | |
575 ctx = repo[node] | |
576 | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
577 if kind == 'files': |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
578 if prefix: |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
579 raise util.Abort( |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
580 _('cannot give prefix when archiving to files')) |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
581 else: |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
582 prefix = archival.tidyprefix(dest, kind, prefix) |
15168 | 583 |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
584 def write(name, mode, islink, getdata): |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
585 if matchfn and not matchfn(name): |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
586 return |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
587 data = getdata() |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
588 if decode: |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
589 data = repo.wwritedata(name, data) |
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
590 archiver.addfile(prefix + name, mode, islink, data) |
15168 | 591 |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
592 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) |
15168 | 593 |
594 if repo.ui.configbool("ui", "archivemeta", True): | |
595 def metadata(): | |
596 base = 'repo: %s\nnode: %s\nbranch: %s\n' % ( | |
597 hex(repo.changelog.node(0)), hex(node), ctx.branch()) | |
598 | |
599 tags = ''.join('tag: %s\n' % t for t in ctx.tags() | |
600 if repo.tagtype(t) == 'global') | |
601 if not tags: | |
602 repo.ui.pushbuffer() | |
603 opts = {'template': '{latesttag}\n{latesttagdistance}', | |
604 'style': '', 'patch': None, 'git': None} | |
605 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx) | |
606 ltags, dist = repo.ui.popbuffer().split('\n') | |
607 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':')) | |
608 tags += 'latesttagdistance: %s\n' % dist | |
609 | |
610 return base + tags | |
611 | |
612 write('.hg_archival.txt', 0644, False, metadata) | |
613 | |
614 for f in ctx: | |
615 ff = ctx.flags(f) | |
616 getdata = ctx[f].data | |
617 if lfutil.isstandin(f): | |
618 path = lfutil.findfile(repo, getdata().strip()) | |
619 f = lfutil.splitstandin(f) | |
620 | |
621 def getdatafn(): | |
622 try: | |
623 fd = open(path, 'rb') | |
624 return fd.read() | |
625 finally: | |
626 fd.close() | |
627 | |
628 getdata = getdatafn | |
629 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata) | |
630 | |
631 if subrepos: | |
632 for subpath in ctx.substate: | |
633 sub = ctx.sub(subpath) | |
634 try: | |
635 sub.archive(repo.ui, archiver, prefix) | |
636 except TypeError: | |
637 sub.archive(archiver, prefix) | |
638 | |
639 archiver.done() | |
640 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
641 # If a largefile is modified, the change is not reflected in its |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
642 # standin until a commit. cmdutil.bailifchanged() raises an exception |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
643 # if the repo has uncommitted changes. Wrap it to also check if |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
644 # largefiles were changed. This is used by bisect and backout. |
15168 | 645 def override_bailifchanged(orig, repo): |
646 orig(repo) | |
647 repo.lfstatus = True | |
648 modified, added, removed, deleted = repo.status()[:4] | |
649 repo.lfstatus = False | |
650 if modified or added or removed or deleted: | |
651 raise util.Abort(_('outstanding uncommitted changes')) | |
652 | |
653 # Fetch doesn't use cmdutil.bail_if_changed so override it to add the check | |
654 def override_fetch(orig, ui, repo, *pats, **opts): | |
655 repo.lfstatus = True | |
656 modified, added, removed, deleted = repo.status()[:4] | |
657 repo.lfstatus = False | |
658 if modified or added or removed or deleted: | |
659 raise util.Abort(_('outstanding uncommitted changes')) | |
660 return orig(ui, repo, *pats, **opts) | |
661 | |
662 def override_forget(orig, ui, repo, *pats, **opts): | |
663 installnormalfilesmatchfn(repo[None].manifest()) | |
664 orig(ui, repo, *pats, **opts) | |
665 restorematchfn() | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
666 m = scmutil.match(repo[None], pats, opts) |
15168 | 667 |
668 try: | |
669 repo.lfstatus = True | |
670 s = repo.status(match=m, clean=True) | |
671 finally: | |
672 repo.lfstatus = False | |
673 forget = sorted(s[0] + s[1] + s[3] + s[6]) | |
674 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()] | |
675 | |
676 for f in forget: | |
677 if lfutil.standin(f) not in repo.dirstate and not \ | |
678 os.path.isdir(m.rel(lfutil.standin(f))): | |
679 ui.warn(_('not removing %s: file is already untracked\n') | |
680 % m.rel(f)) | |
681 | |
682 for f in forget: | |
683 if ui.verbose or not m.exact(f): | |
684 ui.status(_('removing %s\n') % m.rel(f)) | |
685 | |
686 # Need to lock because standin files are deleted then removed from the | |
687 # repository and we could race inbetween. | |
688 wlock = repo.wlock() | |
689 try: | |
690 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
691 for f in forget: | |
692 if lfdirstate[f] == 'a': | |
693 lfdirstate.drop(f) | |
694 else: | |
695 lfdirstate.remove(f) | |
696 lfdirstate.write() | |
697 lfutil.repo_remove(repo, [lfutil.standin(f) for f in forget], | |
698 unlink=True) | |
699 finally: | |
700 wlock.release() | |
701 | |
702 def getoutgoinglfiles(ui, repo, dest=None, **opts): | |
703 dest = ui.expandpath(dest or 'default-push', dest or 'default') | |
704 dest, branches = hg.parseurl(dest, opts.get('branch')) | |
705 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev')) | |
706 if revs: | |
707 revs = [repo.lookup(rev) for rev in revs] | |
708 | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
709 remoteui = hg.remoteui |
15168 | 710 |
711 try: | |
712 remote = hg.repository(remoteui(repo, opts), dest) | |
713 except error.RepoError: | |
714 return None | |
715 o = lfutil.findoutgoing(repo, remote, False) | |
716 if not o: | |
717 return None | |
718 o = repo.changelog.nodesbetween(o, revs)[0] | |
719 if opts.get('newest_first'): | |
720 o.reverse() | |
721 | |
722 toupload = set() | |
723 for n in o: | |
724 parents = [p for p in repo.changelog.parents(n) if p != node.nullid] | |
725 ctx = repo[n] | |
726 files = set(ctx.files()) | |
727 if len(parents) == 2: | |
728 mc = ctx.manifest() | |
729 mp1 = ctx.parents()[0].manifest() | |
730 mp2 = ctx.parents()[1].manifest() | |
731 for f in mp1: | |
732 if f not in mc: | |
733 files.add(f) | |
734 for f in mp2: | |
735 if f not in mc: | |
736 files.add(f) | |
737 for f in mc: | |
738 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None): | |
739 files.add(f) | |
15255
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
740 toupload = toupload.union( |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
741 set([f for f in files if lfutil.isstandin(f) and f in ctx])) |
15168 | 742 return toupload |
743 | |
744 def override_outgoing(orig, ui, repo, dest=None, **opts): | |
745 orig(ui, repo, dest, **opts) | |
746 | |
747 if opts.pop('large', None): | |
748 toupload = getoutgoinglfiles(ui, repo, dest, **opts) | |
749 if toupload is None: | |
750 ui.status(_('largefiles: No remote repo\n')) | |
751 else: | |
752 ui.status(_('largefiles to upload:\n')) | |
753 for file in toupload: | |
754 ui.status(lfutil.splitstandin(file) + '\n') | |
755 ui.status('\n') | |
756 | |
757 def override_summary(orig, ui, repo, *pats, **opts): | |
758 orig(ui, repo, *pats, **opts) | |
759 | |
760 if opts.pop('large', None): | |
761 toupload = getoutgoinglfiles(ui, repo, None, **opts) | |
762 if toupload is None: | |
763 ui.status(_('largefiles: No remote repo\n')) | |
764 else: | |
765 ui.status(_('largefiles: %d to upload\n') % len(toupload)) | |
766 | |
767 def override_addremove(orig, ui, repo, *pats, **opts): | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
768 # Check if the parent or child has largefiles; if so, disallow |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
769 # addremove. If there is a symlink in the manifest then getting |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
770 # the manifest throws an exception: catch it and let addremove |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
771 # deal with it. |
15168 | 772 try: |
773 manifesttip = set(repo['tip'].manifest()) | |
774 except util.Abort: | |
775 manifesttip = set() | |
776 try: | |
777 manifestworking = set(repo[None].manifest()) | |
778 except util.Abort: | |
779 manifestworking = set() | |
780 | |
781 # Manifests are only iterable so turn them into sets then union | |
782 for file in manifesttip.union(manifestworking): | |
783 if file.startswith(lfutil.shortname): | |
784 raise util.Abort( | |
785 _('addremove cannot be run on a repo with largefiles')) | |
786 | |
787 return orig(ui, repo, *pats, **opts) | |
788 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
789 # Calling purge with --all will cause the largefiles to be deleted. |
15168 | 790 # Override repo.status to prevent this from happening. |
791 def override_purge(orig, ui, repo, *dirs, **opts): | |
792 oldstatus = repo.status | |
793 def override_status(node1='.', node2=None, match=None, ignored=False, | |
794 clean=False, unknown=False, listsubrepos=False): | |
795 r = oldstatus(node1, node2, match, ignored, clean, unknown, | |
796 listsubrepos) | |
797 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
798 modified, added, removed, deleted, unknown, ignored, clean = r | |
799 unknown = [f for f in unknown if lfdirstate[f] == '?'] | |
800 ignored = [f for f in ignored if lfdirstate[f] == '?'] | |
801 return modified, added, removed, deleted, unknown, ignored, clean | |
802 repo.status = override_status | |
803 orig(ui, repo, *dirs, **opts) | |
804 repo.status = oldstatus | |
805 | |
806 def override_rollback(orig, ui, repo, **opts): | |
807 result = orig(ui, repo, **opts) | |
808 merge.update(repo, node=None, branchmerge=False, force=True, | |
809 partial=lfutil.isstandin) | |
810 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
811 lfiles = lfutil.listlfiles(repo) | |
812 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev()) | |
813 for file in lfiles: | |
814 if file in oldlfiles: | |
815 lfdirstate.normallookup(file) | |
816 else: | |
817 lfdirstate.add(file) | |
818 lfdirstate.write() | |
819 return result |