Mercurial > hg-stable
annotate hgext/largefiles/overrides.py @ 15305:683f417fa538 stable
largefiles: tidy imports
- no need to defensively import scmutil
- remove duplicate
- unwrap non-long line
author | Greg Ward <greg@gerg.ca> |
---|---|
date | Sun, 16 Oct 2011 10:29:51 -0400 |
parents | db7b09e689f1 |
children | 94527d67f3da |
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 | |
27 def override_match(repo, pats=[], opts={}, globbed=False, | |
28 default='relpath'): | |
29 match = oldmatch(repo, pats, opts, globbed, default) | |
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) |
15168 | 301 return os.path.join(os.path.relpath('.', repo.getcwd()), |
302 lfutil.standin(path)) | |
303 | |
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
|
304 fullpats = scmutil.expandpats(pats) |
15168 | 305 dest = fullpats[-1] |
306 | |
307 if os.path.isdir(dest): | |
308 if not os.path.isdir(makestandin(dest)): | |
309 os.makedirs(makestandin(dest)) | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
310 # 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
|
311 # 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
|
312 # 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
|
313 # match largefiles and run it again. |
15168 | 314 nonormalfiles = False |
315 nolfiles = False | |
316 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
|
317 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
|
318 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
|
319 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
|
320 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
|
321 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
|
322 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
|
323 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
|
324 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
|
325 result = 0 |
15168 | 326 finally: |
327 restorematchfn() | |
328 | |
329 # The first rename can cause our current working directory to be removed. | |
330 # In that case there is nothing left to copy/rename so just quit. | |
331 try: | |
332 repo.getcwd() | |
333 except OSError: | |
334 return result | |
335 | |
336 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
|
337 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
|
338 # 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
|
339 # 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
|
340 wlock = repo.wlock() |
15168 | 341 |
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
|
342 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
|
343 oldmatch = None # for the closure |
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 def override_match(repo, pats=[], opts={}, globbed=False, |
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 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
|
346 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
|
347 # 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
|
348 # 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
|
349 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
|
350 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
|
351 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
|
352 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
|
353 newpats.append(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
|
354 match = oldmatch(repo, newpats, opts, globbed, default) |
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 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
|
356 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
|
357 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
|
358 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
|
359 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
|
360 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
|
361 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
|
362 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
|
363 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
|
364 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
|
365 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
|
366 listpats = [] |
15168 | 367 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
|
368 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
|
369 listpats.append(pat) |
15168 | 370 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
|
371 listpats.append(makestandin(pat)) |
15168 | 372 |
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
|
373 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
|
374 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
|
375 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
|
376 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
|
377 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
|
378 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
|
379 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
|
380 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
|
381 _('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
|
382 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
|
383 origcopyfile(src, dest) |
15168 | 384 |
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
|
385 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
|
386 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
|
387 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
|
388 util.copyfile = origcopyfile |
15168 | 389 |
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
|
390 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
|
391 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
|
392 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
|
393 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
|
394 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
|
395 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
|
396 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
|
397 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
|
398 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
|
399 os.rename(srclfile, 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
|
400 lfdirstate.remove(os.path.relpath(srclfile, |
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 repo.root)) |
018608160299
largefiles: use separate try/except and try/finally as needed for python2.4
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15255
diff
changeset
|
402 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
|
403 util.copyfile(srclfile, 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
|
404 lfdirstate.add(os.path.relpath(destlfile, |
15168 | 405 repo.root)) |
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
|
406 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
|
407 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
|
408 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
|
409 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
|
410 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
|
411 nolfiles = True |
15168 | 412 finally: |
413 restorematchfn() | |
414 wlock.release() | |
415 | |
416 if nolfiles and nonormalfiles: | |
417 raise util.Abort(_('no files to copy')) | |
418 | |
419 return result | |
420 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
421 # 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
|
422 # 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
|
423 # 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
|
424 # the necessary largefiles. |
15168 | 425 # |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
426 # 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
|
427 # 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
|
428 # 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
|
429 # 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
|
430 # to their proper state |
15168 | 431 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
|
432 # 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
|
433 # 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
|
434 # prevent others from changing them in their incorrect state. |
15168 | 435 wlock = repo.wlock() |
436 try: | |
437 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
438 (modified, added, removed, missing, unknown, ignored, clean) = \ | |
439 lfutil.lfdirstate_status(lfdirstate, repo, repo['.'].rev()) | |
440 for lfile in modified: | |
441 lfutil.updatestandin(repo, lfutil.standin(lfile)) | |
442 | |
443 try: | |
444 ctx = repo[opts.get('rev')] | |
445 oldmatch = None # for the closure | |
446 def override_match(ctxorrepo, pats=[], opts={}, globbed=False, | |
447 default='relpath'): | |
15169
aa262fff87ac
largefile: fix up hasattr usage
Matt Mackall <mpm@selenic.com>
parents:
15168
diff
changeset
|
448 if util.safehasattr(ctxorrepo, 'match'): |
15168 | 449 ctx0 = ctxorrepo |
450 else: | |
451 ctx0 = ctxorrepo[None] | |
452 match = oldmatch(ctxorrepo, pats, opts, globbed, default) | |
453 m = copy.copy(match) | |
454 def tostandin(f): | |
455 if lfutil.standin(f) in ctx0 or lfutil.standin(f) in ctx: | |
456 return lfutil.standin(f) | |
457 elif lfutil.standin(f) in repo[None]: | |
458 return None | |
459 return f | |
460 m._files = [tostandin(f) for f in m._files] | |
461 m._files = [f for f in m._files if f is not None] | |
462 m._fmap = set(m._files) | |
463 orig_matchfn = m.matchfn | |
464 def matchfn(f): | |
465 if lfutil.isstandin(f): | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
466 # 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
|
467 # 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
|
468 # otherwise we accidentally revert changes to other |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
469 # 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
|
470 # repo object to keep the list of largefiles for us |
15168 | 471 # later. |
472 if orig_matchfn(lfutil.splitstandin(f)) and \ | |
473 (f in repo[None] or f in ctx): | |
474 lfileslist = getattr(repo, '_lfilestoupdate', []) | |
475 lfileslist.append(lfutil.splitstandin(f)) | |
476 repo._lfilestoupdate = lfileslist | |
477 return True | |
478 else: | |
479 return False | |
480 return orig_matchfn(f) | |
481 m.matchfn = matchfn | |
482 return m | |
483 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
|
484 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
|
485 matches = override_match(repo[None], pats, opts) |
15168 | 486 orig(ui, repo, *pats, **opts) |
487 finally: | |
488 restorematchfn() | |
489 lfileslist = getattr(repo, '_lfilestoupdate', []) | |
15170
c1a4a3220711
largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents:
15169
diff
changeset
|
490 lfcommands.updatelfiles(ui, repo, filelist=lfileslist, |
c1a4a3220711
largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents:
15169
diff
changeset
|
491 printmessage=False) |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
492 |
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
493 # empty out the largefiles list so we start fresh next time |
15168 | 494 repo._lfilestoupdate = [] |
495 for lfile in modified: | |
496 if lfile in lfileslist: | |
497 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\ | |
498 in repo['.']: | |
499 lfutil.writestandin(repo, lfutil.standin(lfile), | |
500 repo['.'][lfile].data().strip(), | |
501 'x' in repo['.'][lfile].flags()) | |
502 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
503 for lfile in added: | |
504 standin = lfutil.standin(lfile) | |
505 if standin not in ctx and (standin in matches or opts.get('all')): | |
506 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
|
507 lfdirstate.drop(lfile) |
15168 | 508 util.unlinkpath(repo.wjoin(standin)) |
509 lfdirstate.write() | |
510 finally: | |
511 wlock.release() | |
512 | |
513 def hg_update(orig, repo, node): | |
514 result = orig(repo, node) | |
515 # XXX check if it worked first | |
516 lfcommands.updatelfiles(repo.ui, repo) | |
517 return result | |
518 | |
519 def hg_clean(orig, repo, node, show_stats=True): | |
520 result = orig(repo, node, show_stats) | |
521 lfcommands.updatelfiles(repo.ui, repo) | |
522 return result | |
523 | |
524 def hg_merge(orig, repo, node, force=None, remind=True): | |
525 result = orig(repo, node, force, remind) | |
526 lfcommands.updatelfiles(repo.ui, repo) | |
527 return result | |
528 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
529 # 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
|
530 # 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
|
531 # working copy |
15168 | 532 def override_pull(orig, ui, repo, source=None, **opts): |
533 if opts.get('rebase', False): | |
534 repo._isrebasing = True | |
535 try: | |
536 if opts.get('update'): | |
537 del opts['update'] | |
538 ui.debug('--update and --rebase are not compatible, ignoring ' | |
539 'the update flag\n') | |
540 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
|
541 cmdutil.bailifchanged(repo) |
15168 | 542 revsprepull = len(repo) |
543 origpostincoming = commands.postincoming | |
544 def _dummy(*args, **kwargs): | |
545 pass | |
546 commands.postincoming = _dummy | |
547 repo.lfpullsource = source | |
548 if not source: | |
549 source = 'default' | |
550 try: | |
551 result = commands.pull(ui, repo, source, **opts) | |
552 finally: | |
553 commands.postincoming = origpostincoming | |
554 revspostpull = len(repo) | |
555 if revspostpull > revsprepull: | |
556 result = result or rebase.rebase(ui, repo) | |
557 finally: | |
558 repo._isrebasing = False | |
559 else: | |
560 repo.lfpullsource = source | |
561 if not source: | |
562 source = 'default' | |
563 result = orig(ui, repo, source, **opts) | |
564 return result | |
565 | |
566 def override_rebase(orig, ui, repo, **opts): | |
567 repo._isrebasing = True | |
568 try: | |
569 orig(ui, repo, **opts) | |
570 finally: | |
571 repo._isrebasing = False | |
572 | |
573 def override_archive(orig, repo, dest, node, kind, decode=True, matchfn=None, | |
574 prefix=None, mtime=None, subrepos=None): | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
575 # 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
|
576 # largefile caches, neither of which are modified. |
15168 | 577 lfcommands.cachelfiles(repo.ui, repo, node) |
578 | |
579 if kind not in archival.archivers: | |
580 raise util.Abort(_("unknown archive type '%s'") % kind) | |
581 | |
582 ctx = repo[node] | |
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 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
|
585 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
|
586 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
|
587 _('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
|
588 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
|
589 prefix = archival.tidyprefix(dest, kind, prefix) |
15168 | 590 |
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
|
591 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
|
592 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
|
593 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
|
594 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
|
595 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
|
596 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
|
597 archiver.addfile(prefix + name, mode, islink, data) |
15168 | 598 |
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
|
599 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) |
15168 | 600 |
601 if repo.ui.configbool("ui", "archivemeta", True): | |
602 def metadata(): | |
603 base = 'repo: %s\nnode: %s\nbranch: %s\n' % ( | |
604 hex(repo.changelog.node(0)), hex(node), ctx.branch()) | |
605 | |
606 tags = ''.join('tag: %s\n' % t for t in ctx.tags() | |
607 if repo.tagtype(t) == 'global') | |
608 if not tags: | |
609 repo.ui.pushbuffer() | |
610 opts = {'template': '{latesttag}\n{latesttagdistance}', | |
611 'style': '', 'patch': None, 'git': None} | |
612 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx) | |
613 ltags, dist = repo.ui.popbuffer().split('\n') | |
614 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':')) | |
615 tags += 'latesttagdistance: %s\n' % dist | |
616 | |
617 return base + tags | |
618 | |
619 write('.hg_archival.txt', 0644, False, metadata) | |
620 | |
621 for f in ctx: | |
622 ff = ctx.flags(f) | |
623 getdata = ctx[f].data | |
624 if lfutil.isstandin(f): | |
625 path = lfutil.findfile(repo, getdata().strip()) | |
626 f = lfutil.splitstandin(f) | |
627 | |
628 def getdatafn(): | |
629 try: | |
630 fd = open(path, 'rb') | |
631 return fd.read() | |
632 finally: | |
633 fd.close() | |
634 | |
635 getdata = getdatafn | |
636 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata) | |
637 | |
638 if subrepos: | |
639 for subpath in ctx.substate: | |
640 sub = ctx.sub(subpath) | |
641 try: | |
642 sub.archive(repo.ui, archiver, prefix) | |
643 except TypeError: | |
644 sub.archive(archiver, prefix) | |
645 | |
646 archiver.done() | |
647 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
648 # 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
|
649 # 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
|
650 # 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
|
651 # largefiles were changed. This is used by bisect and backout. |
15168 | 652 def override_bailifchanged(orig, repo): |
653 orig(repo) | |
654 repo.lfstatus = True | |
655 modified, added, removed, deleted = repo.status()[:4] | |
656 repo.lfstatus = False | |
657 if modified or added or removed or deleted: | |
658 raise util.Abort(_('outstanding uncommitted changes')) | |
659 | |
660 # Fetch doesn't use cmdutil.bail_if_changed so override it to add the check | |
661 def override_fetch(orig, ui, repo, *pats, **opts): | |
662 repo.lfstatus = True | |
663 modified, added, removed, deleted = repo.status()[:4] | |
664 repo.lfstatus = False | |
665 if modified or added or removed or deleted: | |
666 raise util.Abort(_('outstanding uncommitted changes')) | |
667 return orig(ui, repo, *pats, **opts) | |
668 | |
669 def override_forget(orig, ui, repo, *pats, **opts): | |
670 installnormalfilesmatchfn(repo[None].manifest()) | |
671 orig(ui, repo, *pats, **opts) | |
672 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
|
673 m = scmutil.match(repo[None], pats, opts) |
15168 | 674 |
675 try: | |
676 repo.lfstatus = True | |
677 s = repo.status(match=m, clean=True) | |
678 finally: | |
679 repo.lfstatus = False | |
680 forget = sorted(s[0] + s[1] + s[3] + s[6]) | |
681 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()] | |
682 | |
683 for f in forget: | |
684 if lfutil.standin(f) not in repo.dirstate and not \ | |
685 os.path.isdir(m.rel(lfutil.standin(f))): | |
686 ui.warn(_('not removing %s: file is already untracked\n') | |
687 % m.rel(f)) | |
688 | |
689 for f in forget: | |
690 if ui.verbose or not m.exact(f): | |
691 ui.status(_('removing %s\n') % m.rel(f)) | |
692 | |
693 # Need to lock because standin files are deleted then removed from the | |
694 # repository and we could race inbetween. | |
695 wlock = repo.wlock() | |
696 try: | |
697 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
698 for f in forget: | |
699 if lfdirstate[f] == 'a': | |
700 lfdirstate.drop(f) | |
701 else: | |
702 lfdirstate.remove(f) | |
703 lfdirstate.write() | |
704 lfutil.repo_remove(repo, [lfutil.standin(f) for f in forget], | |
705 unlink=True) | |
706 finally: | |
707 wlock.release() | |
708 | |
709 def getoutgoinglfiles(ui, repo, dest=None, **opts): | |
710 dest = ui.expandpath(dest or 'default-push', dest or 'default') | |
711 dest, branches = hg.parseurl(dest, opts.get('branch')) | |
712 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev')) | |
713 if revs: | |
714 revs = [repo.lookup(rev) for rev in revs] | |
715 | |
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
|
716 remoteui = hg.remoteui |
15168 | 717 |
718 try: | |
719 remote = hg.repository(remoteui(repo, opts), dest) | |
720 except error.RepoError: | |
721 return None | |
722 o = lfutil.findoutgoing(repo, remote, False) | |
723 if not o: | |
724 return None | |
725 o = repo.changelog.nodesbetween(o, revs)[0] | |
726 if opts.get('newest_first'): | |
727 o.reverse() | |
728 | |
729 toupload = set() | |
730 for n in o: | |
731 parents = [p for p in repo.changelog.parents(n) if p != node.nullid] | |
732 ctx = repo[n] | |
733 files = set(ctx.files()) | |
734 if len(parents) == 2: | |
735 mc = ctx.manifest() | |
736 mp1 = ctx.parents()[0].manifest() | |
737 mp2 = ctx.parents()[1].manifest() | |
738 for f in mp1: | |
739 if f not in mc: | |
740 files.add(f) | |
741 for f in mp2: | |
742 if f not in mc: | |
743 files.add(f) | |
744 for f in mc: | |
745 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None): | |
746 files.add(f) | |
15255
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
747 toupload = toupload.union( |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15254
diff
changeset
|
748 set([f for f in files if lfutil.isstandin(f) and f in ctx])) |
15168 | 749 return toupload |
750 | |
751 def override_outgoing(orig, ui, repo, dest=None, **opts): | |
752 orig(ui, repo, dest, **opts) | |
753 | |
754 if opts.pop('large', None): | |
755 toupload = getoutgoinglfiles(ui, repo, dest, **opts) | |
756 if toupload is None: | |
757 ui.status(_('largefiles: No remote repo\n')) | |
758 else: | |
759 ui.status(_('largefiles to upload:\n')) | |
760 for file in toupload: | |
761 ui.status(lfutil.splitstandin(file) + '\n') | |
762 ui.status('\n') | |
763 | |
764 def override_summary(orig, ui, repo, *pats, **opts): | |
765 orig(ui, repo, *pats, **opts) | |
766 | |
767 if opts.pop('large', None): | |
768 toupload = getoutgoinglfiles(ui, repo, None, **opts) | |
769 if toupload is None: | |
770 ui.status(_('largefiles: No remote repo\n')) | |
771 else: | |
772 ui.status(_('largefiles: %d to upload\n') % len(toupload)) | |
773 | |
774 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
|
775 # 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
|
776 # 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
|
777 # 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
|
778 # deal with it. |
15168 | 779 try: |
780 manifesttip = set(repo['tip'].manifest()) | |
781 except util.Abort: | |
782 manifesttip = set() | |
783 try: | |
784 manifestworking = set(repo[None].manifest()) | |
785 except util.Abort: | |
786 manifestworking = set() | |
787 | |
788 # Manifests are only iterable so turn them into sets then union | |
789 for file in manifesttip.union(manifestworking): | |
790 if file.startswith(lfutil.shortname): | |
791 raise util.Abort( | |
792 _('addremove cannot be run on a repo with largefiles')) | |
793 | |
794 return orig(ui, repo, *pats, **opts) | |
795 | |
15254
dd03d3a9f888
largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
796 # Calling purge with --all will cause the largefiles to be deleted. |
15168 | 797 # Override repo.status to prevent this from happening. |
798 def override_purge(orig, ui, repo, *dirs, **opts): | |
799 oldstatus = repo.status | |
800 def override_status(node1='.', node2=None, match=None, ignored=False, | |
801 clean=False, unknown=False, listsubrepos=False): | |
802 r = oldstatus(node1, node2, match, ignored, clean, unknown, | |
803 listsubrepos) | |
804 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
805 modified, added, removed, deleted, unknown, ignored, clean = r | |
806 unknown = [f for f in unknown if lfdirstate[f] == '?'] | |
807 ignored = [f for f in ignored if lfdirstate[f] == '?'] | |
808 return modified, added, removed, deleted, unknown, ignored, clean | |
809 repo.status = override_status | |
810 orig(ui, repo, *dirs, **opts) | |
811 repo.status = oldstatus | |
812 | |
813 def override_rollback(orig, ui, repo, **opts): | |
814 result = orig(ui, repo, **opts) | |
815 merge.update(repo, node=None, branchmerge=False, force=True, | |
816 partial=lfutil.isstandin) | |
817 lfdirstate = lfutil.openlfdirstate(ui, repo) | |
818 lfiles = lfutil.listlfiles(repo) | |
819 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev()) | |
820 for file in lfiles: | |
821 if file in oldlfiles: | |
822 lfdirstate.normallookup(file) | |
823 else: | |
824 lfdirstate.add(file) | |
825 lfdirstate.write() | |
826 return result |