|
@@
-1,1105
+1,1106
b''
|
|
1
|
# Copyright 2009-2010 Gregory P. Ward
|
|
1
|
# Copyright 2009-2010 Gregory P. Ward
|
|
2
|
# Copyright 2009-2010 Intelerad Medical Systems Incorporated
|
|
2
|
# Copyright 2009-2010 Intelerad Medical Systems Incorporated
|
|
3
|
# Copyright 2010-2011 Fog Creek Software
|
|
3
|
# Copyright 2010-2011 Fog Creek Software
|
|
4
|
# Copyright 2010-2011 Unity Technologies
|
|
4
|
# Copyright 2010-2011 Unity Technologies
|
|
5
|
#
|
|
5
|
#
|
|
6
|
# This software may be used and distributed according to the terms of the
|
|
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.
|
|
7
|
# GNU General Public License version 2 or any later version.
|
|
8
|
|
|
8
|
|
|
9
|
'''Overridden Mercurial commands and functions for the largefiles extension'''
|
|
9
|
'''Overridden Mercurial commands and functions for the largefiles extension'''
|
|
10
|
|
|
10
|
|
|
11
|
import os
|
|
11
|
import os
|
|
12
|
import copy
|
|
12
|
import copy
|
|
13
|
|
|
13
|
|
|
14
|
from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
|
|
14
|
from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
|
|
15
|
node, archival, error, merge
|
|
15
|
node, archival, error, merge
|
|
16
|
from mercurial.i18n import _
|
|
16
|
from mercurial.i18n import _
|
|
17
|
from mercurial.node import hex
|
|
17
|
from mercurial.node import hex
|
|
18
|
from hgext import rebase
|
|
18
|
from hgext import rebase
|
|
19
|
|
|
19
|
|
|
20
|
import lfutil
|
|
20
|
import lfutil
|
|
21
|
import lfcommands
|
|
21
|
import lfcommands
|
|
22
|
|
|
22
|
|
|
23
|
# -- Utility functions: commonly/repeatedly needed functionality ---------------
|
|
23
|
# -- Utility functions: commonly/repeatedly needed functionality ---------------
|
|
24
|
|
|
24
|
|
|
25
|
def installnormalfilesmatchfn(manifest):
|
|
25
|
def installnormalfilesmatchfn(manifest):
|
|
26
|
'''overrides scmutil.match so that the matcher it returns will ignore all
|
|
26
|
'''overrides scmutil.match so that the matcher it returns will ignore all
|
|
27
|
largefiles'''
|
|
27
|
largefiles'''
|
|
28
|
oldmatch = None # for the closure
|
|
28
|
oldmatch = None # for the closure
|
|
29
|
def overridematch(ctx, pats=[], opts={}, globbed=False,
|
|
29
|
def overridematch(ctx, pats=[], opts={}, globbed=False,
|
|
30
|
default='relpath'):
|
|
30
|
default='relpath'):
|
|
31
|
match = oldmatch(ctx, pats, opts, globbed, default)
|
|
31
|
match = oldmatch(ctx, pats, opts, globbed, default)
|
|
32
|
m = copy.copy(match)
|
|
32
|
m = copy.copy(match)
|
|
33
|
notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
|
|
33
|
notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
|
|
34
|
manifest)
|
|
34
|
manifest)
|
|
35
|
m._files = filter(notlfile, m._files)
|
|
35
|
m._files = filter(notlfile, m._files)
|
|
36
|
m._fmap = set(m._files)
|
|
36
|
m._fmap = set(m._files)
|
|
37
|
origmatchfn = m.matchfn
|
|
37
|
origmatchfn = m.matchfn
|
|
38
|
m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
|
|
38
|
m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
|
|
39
|
return m
|
|
39
|
return m
|
|
40
|
oldmatch = installmatchfn(overridematch)
|
|
40
|
oldmatch = installmatchfn(overridematch)
|
|
41
|
|
|
41
|
|
|
42
|
def installmatchfn(f):
|
|
42
|
def installmatchfn(f):
|
|
43
|
oldmatch = scmutil.match
|
|
43
|
oldmatch = scmutil.match
|
|
44
|
setattr(f, 'oldmatch', oldmatch)
|
|
44
|
setattr(f, 'oldmatch', oldmatch)
|
|
45
|
scmutil.match = f
|
|
45
|
scmutil.match = f
|
|
46
|
return oldmatch
|
|
46
|
return oldmatch
|
|
47
|
|
|
47
|
|
|
48
|
def restorematchfn():
|
|
48
|
def restorematchfn():
|
|
49
|
'''restores scmutil.match to what it was before installnormalfilesmatchfn
|
|
49
|
'''restores scmutil.match to what it was before installnormalfilesmatchfn
|
|
50
|
was called. no-op if scmutil.match is its original function.
|
|
50
|
was called. no-op if scmutil.match is its original function.
|
|
51
|
|
|
51
|
|
|
52
|
Note that n calls to installnormalfilesmatchfn will require n calls to
|
|
52
|
Note that n calls to installnormalfilesmatchfn will require n calls to
|
|
53
|
restore matchfn to reverse'''
|
|
53
|
restore matchfn to reverse'''
|
|
54
|
scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
|
|
54
|
scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
|
|
55
|
|
|
55
|
|
|
56
|
def addlargefiles(ui, repo, *pats, **opts):
|
|
56
|
def addlargefiles(ui, repo, *pats, **opts):
|
|
57
|
large = opts.pop('large', None)
|
|
57
|
large = opts.pop('large', None)
|
|
58
|
lfsize = lfutil.getminsize(
|
|
58
|
lfsize = lfutil.getminsize(
|
|
59
|
ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
|
|
59
|
ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
|
|
60
|
|
|
60
|
|
|
61
|
lfmatcher = None
|
|
61
|
lfmatcher = None
|
|
62
|
if lfutil.islfilesrepo(repo):
|
|
62
|
if lfutil.islfilesrepo(repo):
|
|
63
|
lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
|
|
63
|
lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
|
|
64
|
if lfpats:
|
|
64
|
if lfpats:
|
|
65
|
lfmatcher = match_.match(repo.root, '', list(lfpats))
|
|
65
|
lfmatcher = match_.match(repo.root, '', list(lfpats))
|
|
66
|
|
|
66
|
|
|
67
|
lfnames = []
|
|
67
|
lfnames = []
|
|
68
|
m = scmutil.match(repo[None], pats, opts)
|
|
68
|
m = scmutil.match(repo[None], pats, opts)
|
|
69
|
m.bad = lambda x, y: None
|
|
69
|
m.bad = lambda x, y: None
|
|
70
|
wctx = repo[None]
|
|
70
|
wctx = repo[None]
|
|
71
|
for f in repo.walk(m):
|
|
71
|
for f in repo.walk(m):
|
|
72
|
exact = m.exact(f)
|
|
72
|
exact = m.exact(f)
|
|
73
|
lfile = lfutil.standin(f) in wctx
|
|
73
|
lfile = lfutil.standin(f) in wctx
|
|
74
|
nfile = f in wctx
|
|
74
|
nfile = f in wctx
|
|
75
|
exists = lfile or nfile
|
|
75
|
exists = lfile or nfile
|
|
76
|
|
|
76
|
|
|
77
|
# Don't warn the user when they attempt to add a normal tracked file.
|
|
77
|
# Don't warn the user when they attempt to add a normal tracked file.
|
|
78
|
# The normal add code will do that for us.
|
|
78
|
# The normal add code will do that for us.
|
|
79
|
if exact and exists:
|
|
79
|
if exact and exists:
|
|
80
|
if lfile:
|
|
80
|
if lfile:
|
|
81
|
ui.warn(_('%s already a largefile\n') % f)
|
|
81
|
ui.warn(_('%s already a largefile\n') % f)
|
|
82
|
continue
|
|
82
|
continue
|
|
83
|
|
|
83
|
|
|
84
|
if (exact or not exists) and not lfutil.isstandin(f):
|
|
84
|
if (exact or not exists) and not lfutil.isstandin(f):
|
|
85
|
wfile = repo.wjoin(f)
|
|
85
|
wfile = repo.wjoin(f)
|
|
86
|
|
|
86
|
|
|
87
|
# In case the file was removed previously, but not committed
|
|
87
|
# In case the file was removed previously, but not committed
|
|
88
|
# (issue3507)
|
|
88
|
# (issue3507)
|
|
89
|
if not os.path.exists(wfile):
|
|
89
|
if not os.path.exists(wfile):
|
|
90
|
continue
|
|
90
|
continue
|
|
91
|
|
|
91
|
|
|
92
|
abovemin = (lfsize and
|
|
92
|
abovemin = (lfsize and
|
|
93
|
os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
|
|
93
|
os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
|
|
94
|
if large or abovemin or (lfmatcher and lfmatcher(f)):
|
|
94
|
if large or abovemin or (lfmatcher and lfmatcher(f)):
|
|
95
|
lfnames.append(f)
|
|
95
|
lfnames.append(f)
|
|
96
|
if ui.verbose or not exact:
|
|
96
|
if ui.verbose or not exact:
|
|
97
|
ui.status(_('adding %s as a largefile\n') % m.rel(f))
|
|
97
|
ui.status(_('adding %s as a largefile\n') % m.rel(f))
|
|
98
|
|
|
98
|
|
|
99
|
bad = []
|
|
99
|
bad = []
|
|
100
|
standins = []
|
|
100
|
standins = []
|
|
101
|
|
|
101
|
|
|
102
|
# Need to lock, otherwise there could be a race condition between
|
|
102
|
# Need to lock, otherwise there could be a race condition between
|
|
103
|
# when standins are created and added to the repo.
|
|
103
|
# when standins are created and added to the repo.
|
|
104
|
wlock = repo.wlock()
|
|
104
|
wlock = repo.wlock()
|
|
105
|
try:
|
|
105
|
try:
|
|
106
|
if not opts.get('dry_run'):
|
|
106
|
if not opts.get('dry_run'):
|
|
107
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
107
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
108
|
for f in lfnames:
|
|
108
|
for f in lfnames:
|
|
109
|
standinname = lfutil.standin(f)
|
|
109
|
standinname = lfutil.standin(f)
|
|
110
|
lfutil.writestandin(repo, standinname, hash='',
|
|
110
|
lfutil.writestandin(repo, standinname, hash='',
|
|
111
|
executable=lfutil.getexecutable(repo.wjoin(f)))
|
|
111
|
executable=lfutil.getexecutable(repo.wjoin(f)))
|
|
112
|
standins.append(standinname)
|
|
112
|
standins.append(standinname)
|
|
113
|
if lfdirstate[f] == 'r':
|
|
113
|
if lfdirstate[f] == 'r':
|
|
114
|
lfdirstate.normallookup(f)
|
|
114
|
lfdirstate.normallookup(f)
|
|
115
|
else:
|
|
115
|
else:
|
|
116
|
lfdirstate.add(f)
|
|
116
|
lfdirstate.add(f)
|
|
117
|
lfdirstate.write()
|
|
117
|
lfdirstate.write()
|
|
118
|
bad += [lfutil.splitstandin(f)
|
|
118
|
bad += [lfutil.splitstandin(f)
|
|
119
|
for f in lfutil.repoadd(repo, standins)
|
|
119
|
for f in lfutil.repoadd(repo, standins)
|
|
120
|
if f in m.files()]
|
|
120
|
if f in m.files()]
|
|
121
|
finally:
|
|
121
|
finally:
|
|
122
|
wlock.release()
|
|
122
|
wlock.release()
|
|
123
|
return bad
|
|
123
|
return bad
|
|
124
|
|
|
124
|
|
|
125
|
def removelargefiles(ui, repo, *pats, **opts):
|
|
125
|
def removelargefiles(ui, repo, *pats, **opts):
|
|
126
|
after = opts.get('after')
|
|
126
|
after = opts.get('after')
|
|
127
|
if not pats and not after:
|
|
127
|
if not pats and not after:
|
|
128
|
raise util.Abort(_('no files specified'))
|
|
128
|
raise util.Abort(_('no files specified'))
|
|
129
|
m = scmutil.match(repo[None], pats, opts)
|
|
129
|
m = scmutil.match(repo[None], pats, opts)
|
|
130
|
try:
|
|
130
|
try:
|
|
131
|
repo.lfstatus = True
|
|
131
|
repo.lfstatus = True
|
|
132
|
s = repo.status(match=m, clean=True)
|
|
132
|
s = repo.status(match=m, clean=True)
|
|
133
|
finally:
|
|
133
|
finally:
|
|
134
|
repo.lfstatus = False
|
|
134
|
repo.lfstatus = False
|
|
135
|
manifest = repo[None].manifest()
|
|
135
|
manifest = repo[None].manifest()
|
|
136
|
modified, added, deleted, clean = [[f for f in list
|
|
136
|
modified, added, deleted, clean = [[f for f in list
|
|
137
|
if lfutil.standin(f) in manifest]
|
|
137
|
if lfutil.standin(f) in manifest]
|
|
138
|
for list in [s[0], s[1], s[3], s[6]]]
|
|
138
|
for list in [s[0], s[1], s[3], s[6]]]
|
|
139
|
|
|
139
|
|
|
140
|
def warn(files, reason):
|
|
140
|
def warn(files, reason):
|
|
141
|
for f in files:
|
|
141
|
for f in files:
|
|
142
|
ui.warn(_('not removing %s: %s (use forget to undo)\n')
|
|
142
|
ui.warn(_('not removing %s: %s (use forget to undo)\n')
|
|
143
|
% (m.rel(f), reason))
|
|
143
|
% (m.rel(f), reason))
|
|
144
|
return int(len(files) > 0)
|
|
144
|
return int(len(files) > 0)
|
|
145
|
|
|
145
|
|
|
146
|
result = 0
|
|
146
|
result = 0
|
|
147
|
|
|
147
|
|
|
148
|
if after:
|
|
148
|
if after:
|
|
149
|
remove, forget = deleted, []
|
|
149
|
remove, forget = deleted, []
|
|
150
|
result = warn(modified + added + clean, _('file still exists'))
|
|
150
|
result = warn(modified + added + clean, _('file still exists'))
|
|
151
|
else:
|
|
151
|
else:
|
|
152
|
remove, forget = deleted + clean, []
|
|
152
|
remove, forget = deleted + clean, []
|
|
153
|
result = warn(modified, _('file is modified'))
|
|
153
|
result = warn(modified, _('file is modified'))
|
|
154
|
result = warn(added, _('file has been marked for add')) or result
|
|
154
|
result = warn(added, _('file has been marked for add')) or result
|
|
155
|
|
|
155
|
|
|
156
|
for f in sorted(remove + forget):
|
|
156
|
for f in sorted(remove + forget):
|
|
157
|
if ui.verbose or not m.exact(f):
|
|
157
|
if ui.verbose or not m.exact(f):
|
|
158
|
ui.status(_('removing %s\n') % m.rel(f))
|
|
158
|
ui.status(_('removing %s\n') % m.rel(f))
|
|
159
|
|
|
159
|
|
|
160
|
# Need to lock because standin files are deleted then removed from the
|
|
160
|
# Need to lock because standin files are deleted then removed from the
|
|
161
|
# repository and we could race in-between.
|
|
161
|
# repository and we could race in-between.
|
|
162
|
wlock = repo.wlock()
|
|
162
|
wlock = repo.wlock()
|
|
163
|
try:
|
|
163
|
try:
|
|
164
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
164
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
165
|
for f in remove:
|
|
165
|
for f in remove:
|
|
166
|
if not after:
|
|
166
|
if not after:
|
|
167
|
# If this is being called by addremove, notify the user that we
|
|
167
|
# If this is being called by addremove, notify the user that we
|
|
168
|
# are removing the file.
|
|
168
|
# are removing the file.
|
|
169
|
if getattr(repo, "_isaddremove", False):
|
|
169
|
if getattr(repo, "_isaddremove", False):
|
|
170
|
ui.status(_('removing %s\n') % f)
|
|
170
|
ui.status(_('removing %s\n') % f)
|
|
171
|
if os.path.exists(repo.wjoin(f)):
|
|
171
|
if os.path.exists(repo.wjoin(f)):
|
|
172
|
util.unlinkpath(repo.wjoin(f))
|
|
172
|
util.unlinkpath(repo.wjoin(f))
|
|
173
|
lfdirstate.remove(f)
|
|
173
|
lfdirstate.remove(f)
|
|
174
|
lfdirstate.write()
|
|
174
|
lfdirstate.write()
|
|
175
|
forget = [lfutil.standin(f) for f in forget]
|
|
175
|
forget = [lfutil.standin(f) for f in forget]
|
|
176
|
remove = [lfutil.standin(f) for f in remove]
|
|
176
|
remove = [lfutil.standin(f) for f in remove]
|
|
177
|
lfutil.repoforget(repo, forget)
|
|
177
|
lfutil.repoforget(repo, forget)
|
|
178
|
# If this is being called by addremove, let the original addremove
|
|
178
|
# If this is being called by addremove, let the original addremove
|
|
179
|
# function handle this.
|
|
179
|
# function handle this.
|
|
180
|
if not getattr(repo, "_isaddremove", False):
|
|
180
|
if not getattr(repo, "_isaddremove", False):
|
|
181
|
lfutil.reporemove(repo, remove, unlink=True)
|
|
181
|
lfutil.reporemove(repo, remove, unlink=True)
|
|
182
|
else:
|
|
182
|
else:
|
|
183
|
lfutil.reporemove(repo, remove, unlink=False)
|
|
183
|
lfutil.reporemove(repo, remove, unlink=False)
|
|
184
|
finally:
|
|
184
|
finally:
|
|
185
|
wlock.release()
|
|
185
|
wlock.release()
|
|
186
|
|
|
186
|
|
|
187
|
return result
|
|
187
|
return result
|
|
188
|
|
|
188
|
|
|
189
|
# For overriding mercurial.hgweb.webcommands so that largefiles will
|
|
189
|
# For overriding mercurial.hgweb.webcommands so that largefiles will
|
|
190
|
# appear at their right place in the manifests.
|
|
190
|
# appear at their right place in the manifests.
|
|
191
|
def decodepath(orig, path):
|
|
191
|
def decodepath(orig, path):
|
|
192
|
return lfutil.splitstandin(path) or path
|
|
192
|
return lfutil.splitstandin(path) or path
|
|
193
|
|
|
193
|
|
|
194
|
# -- Wrappers: modify existing commands --------------------------------
|
|
194
|
# -- Wrappers: modify existing commands --------------------------------
|
|
195
|
|
|
195
|
|
|
196
|
# Add works by going through the files that the user wanted to add and
|
|
196
|
# Add works by going through the files that the user wanted to add and
|
|
197
|
# checking if they should be added as largefiles. Then it makes a new
|
|
197
|
# checking if they should be added as largefiles. Then it makes a new
|
|
198
|
# matcher which matches only the normal files and runs the original
|
|
198
|
# matcher which matches only the normal files and runs the original
|
|
199
|
# version of add.
|
|
199
|
# version of add.
|
|
200
|
def overrideadd(orig, ui, repo, *pats, **opts):
|
|
200
|
def overrideadd(orig, ui, repo, *pats, **opts):
|
|
201
|
normal = opts.pop('normal')
|
|
201
|
normal = opts.pop('normal')
|
|
202
|
if normal:
|
|
202
|
if normal:
|
|
203
|
if opts.get('large'):
|
|
203
|
if opts.get('large'):
|
|
204
|
raise util.Abort(_('--normal cannot be used with --large'))
|
|
204
|
raise util.Abort(_('--normal cannot be used with --large'))
|
|
205
|
return orig(ui, repo, *pats, **opts)
|
|
205
|
return orig(ui, repo, *pats, **opts)
|
|
206
|
bad = addlargefiles(ui, repo, *pats, **opts)
|
|
206
|
bad = addlargefiles(ui, repo, *pats, **opts)
|
|
207
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
207
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
208
|
result = orig(ui, repo, *pats, **opts)
|
|
208
|
result = orig(ui, repo, *pats, **opts)
|
|
209
|
restorematchfn()
|
|
209
|
restorematchfn()
|
|
210
|
|
|
210
|
|
|
211
|
return (result == 1 or bad) and 1 or 0
|
|
211
|
return (result == 1 or bad) and 1 or 0
|
|
212
|
|
|
212
|
|
|
213
|
def overrideremove(orig, ui, repo, *pats, **opts):
|
|
213
|
def overrideremove(orig, ui, repo, *pats, **opts):
|
|
214
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
214
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
215
|
result = orig(ui, repo, *pats, **opts)
|
|
215
|
result = orig(ui, repo, *pats, **opts)
|
|
216
|
restorematchfn()
|
|
216
|
restorematchfn()
|
|
217
|
return removelargefiles(ui, repo, *pats, **opts) or result
|
|
217
|
return removelargefiles(ui, repo, *pats, **opts) or result
|
|
218
|
|
|
218
|
|
|
219
|
def overridestatusfn(orig, repo, rev2, **opts):
|
|
219
|
def overridestatusfn(orig, repo, rev2, **opts):
|
|
220
|
try:
|
|
220
|
try:
|
|
221
|
repo._repo.lfstatus = True
|
|
221
|
repo._repo.lfstatus = True
|
|
222
|
return orig(repo, rev2, **opts)
|
|
222
|
return orig(repo, rev2, **opts)
|
|
223
|
finally:
|
|
223
|
finally:
|
|
224
|
repo._repo.lfstatus = False
|
|
224
|
repo._repo.lfstatus = False
|
|
225
|
|
|
225
|
|
|
226
|
def overridestatus(orig, ui, repo, *pats, **opts):
|
|
226
|
def overridestatus(orig, ui, repo, *pats, **opts):
|
|
227
|
try:
|
|
227
|
try:
|
|
228
|
repo.lfstatus = True
|
|
228
|
repo.lfstatus = True
|
|
229
|
return orig(ui, repo, *pats, **opts)
|
|
229
|
return orig(ui, repo, *pats, **opts)
|
|
230
|
finally:
|
|
230
|
finally:
|
|
231
|
repo.lfstatus = False
|
|
231
|
repo.lfstatus = False
|
|
232
|
|
|
232
|
|
|
233
|
def overridedirty(orig, repo, ignoreupdate=False):
|
|
233
|
def overridedirty(orig, repo, ignoreupdate=False):
|
|
234
|
try:
|
|
234
|
try:
|
|
235
|
repo._repo.lfstatus = True
|
|
235
|
repo._repo.lfstatus = True
|
|
236
|
return orig(repo, ignoreupdate)
|
|
236
|
return orig(repo, ignoreupdate)
|
|
237
|
finally:
|
|
237
|
finally:
|
|
238
|
repo._repo.lfstatus = False
|
|
238
|
repo._repo.lfstatus = False
|
|
239
|
|
|
239
|
|
|
240
|
def overridelog(orig, ui, repo, *pats, **opts):
|
|
240
|
def overridelog(orig, ui, repo, *pats, **opts):
|
|
241
|
try:
|
|
241
|
try:
|
|
242
|
repo.lfstatus = True
|
|
242
|
repo.lfstatus = True
|
|
243
|
return orig(ui, repo, *pats, **opts)
|
|
243
|
return orig(ui, repo, *pats, **opts)
|
|
244
|
finally:
|
|
244
|
finally:
|
|
245
|
repo.lfstatus = False
|
|
245
|
repo.lfstatus = False
|
|
246
|
|
|
246
|
|
|
247
|
def overrideverify(orig, ui, repo, *pats, **opts):
|
|
247
|
def overrideverify(orig, ui, repo, *pats, **opts):
|
|
248
|
large = opts.pop('large', False)
|
|
248
|
large = opts.pop('large', False)
|
|
249
|
all = opts.pop('lfa', False)
|
|
249
|
all = opts.pop('lfa', False)
|
|
250
|
contents = opts.pop('lfc', False)
|
|
250
|
contents = opts.pop('lfc', False)
|
|
251
|
|
|
251
|
|
|
252
|
result = orig(ui, repo, *pats, **opts)
|
|
252
|
result = orig(ui, repo, *pats, **opts)
|
|
253
|
if large:
|
|
253
|
if large:
|
|
254
|
result = result or lfcommands.verifylfiles(ui, repo, all, contents)
|
|
254
|
result = result or lfcommands.verifylfiles(ui, repo, all, contents)
|
|
255
|
return result
|
|
255
|
return result
|
|
256
|
|
|
256
|
|
|
257
|
# Override needs to refresh standins so that update's normal merge
|
|
257
|
# Override needs to refresh standins so that update's normal merge
|
|
258
|
# will go through properly. Then the other update hook (overriding repo.update)
|
|
258
|
# will go through properly. Then the other update hook (overriding repo.update)
|
|
259
|
# will get the new files. Filemerge is also overridden so that the merge
|
|
259
|
# will get the new files. Filemerge is also overridden so that the merge
|
|
260
|
# will merge standins correctly.
|
|
260
|
# will merge standins correctly.
|
|
261
|
def overrideupdate(orig, ui, repo, *pats, **opts):
|
|
261
|
def overrideupdate(orig, ui, repo, *pats, **opts):
|
|
262
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
262
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
263
|
s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
|
|
263
|
s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
|
|
264
|
False, False)
|
|
264
|
False, False)
|
|
265
|
(unsure, modified, added, removed, missing, unknown, ignored, clean) = s
|
|
265
|
(unsure, modified, added, removed, missing, unknown, ignored, clean) = s
|
|
266
|
|
|
266
|
|
|
267
|
# Need to lock between the standins getting updated and their
|
|
267
|
# Need to lock between the standins getting updated and their
|
|
268
|
# largefiles getting updated
|
|
268
|
# largefiles getting updated
|
|
269
|
wlock = repo.wlock()
|
|
269
|
wlock = repo.wlock()
|
|
270
|
try:
|
|
270
|
try:
|
|
271
|
if opts['check']:
|
|
271
|
if opts['check']:
|
|
272
|
mod = len(modified) > 0
|
|
272
|
mod = len(modified) > 0
|
|
273
|
for lfile in unsure:
|
|
273
|
for lfile in unsure:
|
|
274
|
standin = lfutil.standin(lfile)
|
|
274
|
standin = lfutil.standin(lfile)
|
|
275
|
if repo['.'][standin].data().strip() != \
|
|
275
|
if repo['.'][standin].data().strip() != \
|
|
276
|
lfutil.hashfile(repo.wjoin(lfile)):
|
|
276
|
lfutil.hashfile(repo.wjoin(lfile)):
|
|
277
|
mod = True
|
|
277
|
mod = True
|
|
278
|
else:
|
|
278
|
else:
|
|
279
|
lfdirstate.normal(lfile)
|
|
279
|
lfdirstate.normal(lfile)
|
|
280
|
lfdirstate.write()
|
|
280
|
lfdirstate.write()
|
|
281
|
if mod:
|
|
281
|
if mod:
|
|
282
|
raise util.Abort(_('uncommitted local changes'))
|
|
282
|
raise util.Abort(_('uncommitted local changes'))
|
|
283
|
# XXX handle removed differently
|
|
283
|
# XXX handle removed differently
|
|
284
|
if not opts['clean']:
|
|
284
|
if not opts['clean']:
|
|
285
|
for lfile in unsure + modified + added:
|
|
285
|
for lfile in unsure + modified + added:
|
|
286
|
lfutil.updatestandin(repo, lfutil.standin(lfile))
|
|
286
|
lfutil.updatestandin(repo, lfutil.standin(lfile))
|
|
287
|
finally:
|
|
287
|
finally:
|
|
288
|
wlock.release()
|
|
288
|
wlock.release()
|
|
289
|
return orig(ui, repo, *pats, **opts)
|
|
289
|
return orig(ui, repo, *pats, **opts)
|
|
290
|
|
|
290
|
|
|
291
|
# Before starting the manifest merge, merge.updates will call
|
|
291
|
# Before starting the manifest merge, merge.updates will call
|
|
292
|
# _checkunknown to check if there are any files in the merged-in
|
|
292
|
# _checkunknown to check if there are any files in the merged-in
|
|
293
|
# changeset that collide with unknown files in the working copy.
|
|
293
|
# changeset that collide with unknown files in the working copy.
|
|
294
|
#
|
|
294
|
#
|
|
295
|
# The largefiles are seen as unknown, so this prevents us from merging
|
|
295
|
# The largefiles are seen as unknown, so this prevents us from merging
|
|
296
|
# in a file 'foo' if we already have a largefile with the same name.
|
|
296
|
# in a file 'foo' if we already have a largefile with the same name.
|
|
297
|
#
|
|
297
|
#
|
|
298
|
# The overridden function filters the unknown files by removing any
|
|
298
|
# The overridden function filters the unknown files by removing any
|
|
299
|
# largefiles. This makes the merge proceed and we can then handle this
|
|
299
|
# largefiles. This makes the merge proceed and we can then handle this
|
|
300
|
# case further in the overridden manifestmerge function below.
|
|
300
|
# case further in the overridden manifestmerge function below.
|
|
301
|
def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
|
|
301
|
def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
|
|
302
|
if lfutil.standin(f) in wctx:
|
|
302
|
if lfutil.standin(f) in wctx:
|
|
303
|
return False
|
|
303
|
return False
|
|
304
|
return origfn(repo, wctx, mctx, f)
|
|
304
|
return origfn(repo, wctx, mctx, f)
|
|
305
|
|
|
305
|
|
|
306
|
# The manifest merge handles conflicts on the manifest level. We want
|
|
306
|
# The manifest merge handles conflicts on the manifest level. We want
|
|
307
|
# to handle changes in largefile-ness of files at this level too.
|
|
307
|
# to handle changes in largefile-ness of files at this level too.
|
|
308
|
#
|
|
308
|
#
|
|
309
|
# The strategy is to run the original manifestmerge and then process
|
|
309
|
# The strategy is to run the original manifestmerge and then process
|
|
310
|
# the action list it outputs. There are two cases we need to deal with:
|
|
310
|
# the action list it outputs. There are two cases we need to deal with:
|
|
311
|
#
|
|
311
|
#
|
|
312
|
# 1. Normal file in p1, largefile in p2. Here the largefile is
|
|
312
|
# 1. Normal file in p1, largefile in p2. Here the largefile is
|
|
313
|
# detected via its standin file, which will enter the working copy
|
|
313
|
# detected via its standin file, which will enter the working copy
|
|
314
|
# with a "get" action. It is not "merge" since the standin is all
|
|
314
|
# with a "get" action. It is not "merge" since the standin is all
|
|
315
|
# Mercurial is concerned with at this level -- the link to the
|
|
315
|
# Mercurial is concerned with at this level -- the link to the
|
|
316
|
# existing normal file is not relevant here.
|
|
316
|
# existing normal file is not relevant here.
|
|
317
|
#
|
|
317
|
#
|
|
318
|
# 2. Largefile in p1, normal file in p2. Here we get a "merge" action
|
|
318
|
# 2. Largefile in p1, normal file in p2. Here we get a "merge" action
|
|
319
|
# since the largefile will be present in the working copy and
|
|
319
|
# since the largefile will be present in the working copy and
|
|
320
|
# different from the normal file in p2. Mercurial therefore
|
|
320
|
# different from the normal file in p2. Mercurial therefore
|
|
321
|
# triggers a merge action.
|
|
321
|
# triggers a merge action.
|
|
322
|
#
|
|
322
|
#
|
|
323
|
# In both cases, we prompt the user and emit new actions to either
|
|
323
|
# In both cases, we prompt the user and emit new actions to either
|
|
324
|
# remove the standin (if the normal file was kept) or to remove the
|
|
324
|
# remove the standin (if the normal file was kept) or to remove the
|
|
325
|
# normal file and get the standin (if the largefile was kept). The
|
|
325
|
# normal file and get the standin (if the largefile was kept). The
|
|
326
|
# default prompt answer is to use the largefile version since it was
|
|
326
|
# default prompt answer is to use the largefile version since it was
|
|
327
|
# presumably changed on purpose.
|
|
327
|
# presumably changed on purpose.
|
|
328
|
#
|
|
328
|
#
|
|
329
|
# Finally, the merge.applyupdates function will then take care of
|
|
329
|
# Finally, the merge.applyupdates function will then take care of
|
|
330
|
# writing the files into the working copy and lfcommands.updatelfiles
|
|
330
|
# writing the files into the working copy and lfcommands.updatelfiles
|
|
331
|
# will update the largefiles.
|
|
331
|
# will update the largefiles.
|
|
332
|
def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
|
|
332
|
def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
|
|
333
|
actions = origfn(repo, p1, p2, pa, overwrite, partial)
|
|
333
|
actions = origfn(repo, p1, p2, pa, overwrite, partial)
|
|
334
|
processed = []
|
|
334
|
processed = []
|
|
335
|
|
|
335
|
|
|
336
|
for action in actions:
|
|
336
|
for action in actions:
|
|
337
|
if overwrite:
|
|
337
|
if overwrite:
|
|
338
|
processed.append(action)
|
|
338
|
processed.append(action)
|
|
339
|
continue
|
|
339
|
continue
|
|
340
|
f, m = action[:2]
|
|
340
|
f, m = action[:2]
|
|
341
|
|
|
341
|
|
|
342
|
choices = (_('&Largefile'), _('&Normal file'))
|
|
342
|
choices = (_('&Largefile'), _('&Normal file'))
|
|
343
|
if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
|
|
343
|
if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
|
|
344
|
# Case 1: normal file in the working copy, largefile in
|
|
344
|
# Case 1: normal file in the working copy, largefile in
|
|
345
|
# the second parent
|
|
345
|
# the second parent
|
|
346
|
lfile = lfutil.splitstandin(f)
|
|
346
|
lfile = lfutil.splitstandin(f)
|
|
347
|
standin = f
|
|
347
|
standin = f
|
|
348
|
msg = _('%s has been turned into a largefile\n'
|
|
348
|
msg = _('%s has been turned into a largefile\n'
|
|
349
|
'use (l)argefile or keep as (n)ormal file?') % lfile
|
|
349
|
'use (l)argefile or keep as (n)ormal file?') % lfile
|
|
350
|
if repo.ui.promptchoice(msg, choices, 0) == 0:
|
|
350
|
if repo.ui.promptchoice(msg, choices, 0) == 0:
|
|
351
|
processed.append((lfile, "r"))
|
|
351
|
processed.append((lfile, "r"))
|
|
352
|
processed.append((standin, "g", p2.flags(standin)))
|
|
352
|
processed.append((standin, "g", p2.flags(standin)))
|
|
353
|
else:
|
|
353
|
else:
|
|
354
|
processed.append((standin, "r"))
|
|
354
|
processed.append((standin, "r"))
|
|
355
|
elif m == "g" and lfutil.standin(f) in p1 and f in p2:
|
|
355
|
elif m == "g" and lfutil.standin(f) in p1 and f in p2:
|
|
356
|
# Case 2: largefile in the working copy, normal file in
|
|
356
|
# Case 2: largefile in the working copy, normal file in
|
|
357
|
# the second parent
|
|
357
|
# the second parent
|
|
358
|
standin = lfutil.standin(f)
|
|
358
|
standin = lfutil.standin(f)
|
|
359
|
lfile = f
|
|
359
|
lfile = f
|
|
360
|
msg = _('%s has been turned into a normal file\n'
|
|
360
|
msg = _('%s has been turned into a normal file\n'
|
|
361
|
'keep as (l)argefile or use (n)ormal file?') % lfile
|
|
361
|
'keep as (l)argefile or use (n)ormal file?') % lfile
|
|
362
|
if repo.ui.promptchoice(msg, choices, 0) == 0:
|
|
362
|
if repo.ui.promptchoice(msg, choices, 0) == 0:
|
|
363
|
processed.append((lfile, "r"))
|
|
363
|
processed.append((lfile, "r"))
|
|
364
|
else:
|
|
364
|
else:
|
|
365
|
processed.append((standin, "r"))
|
|
365
|
processed.append((standin, "r"))
|
|
366
|
processed.append((lfile, "g", p2.flags(lfile)))
|
|
366
|
processed.append((lfile, "g", p2.flags(lfile)))
|
|
367
|
else:
|
|
367
|
else:
|
|
368
|
processed.append(action)
|
|
368
|
processed.append(action)
|
|
369
|
|
|
369
|
|
|
370
|
return processed
|
|
370
|
return processed
|
|
371
|
|
|
371
|
|
|
372
|
# Override filemerge to prompt the user about how they wish to merge
|
|
372
|
# Override filemerge to prompt the user about how they wish to merge
|
|
373
|
# largefiles. This will handle identical edits, and copy/rename +
|
|
373
|
# largefiles. This will handle identical edits, and copy/rename +
|
|
374
|
# edit without prompting the user.
|
|
374
|
# edit without prompting the user.
|
|
375
|
def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
|
|
375
|
def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
|
|
376
|
# Use better variable names here. Because this is a wrapper we cannot
|
|
376
|
# Use better variable names here. Because this is a wrapper we cannot
|
|
377
|
# change the variable names in the function declaration.
|
|
377
|
# change the variable names in the function declaration.
|
|
378
|
fcdest, fcother, fcancestor = fcd, fco, fca
|
|
378
|
fcdest, fcother, fcancestor = fcd, fco, fca
|
|
379
|
if not lfutil.isstandin(orig):
|
|
379
|
if not lfutil.isstandin(orig):
|
|
380
|
return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
|
|
380
|
return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
|
|
381
|
else:
|
|
381
|
else:
|
|
382
|
if not fcother.cmp(fcdest): # files identical?
|
|
382
|
if not fcother.cmp(fcdest): # files identical?
|
|
383
|
return None
|
|
383
|
return None
|
|
384
|
|
|
384
|
|
|
385
|
# backwards, use working dir parent as ancestor
|
|
385
|
# backwards, use working dir parent as ancestor
|
|
386
|
if fcancestor == fcother:
|
|
386
|
if fcancestor == fcother:
|
|
387
|
fcancestor = fcdest.parents()[0]
|
|
387
|
fcancestor = fcdest.parents()[0]
|
|
388
|
|
|
388
|
|
|
389
|
if orig != fcother.path():
|
|
389
|
if orig != fcother.path():
|
|
390
|
repo.ui.status(_('merging %s and %s to %s\n')
|
|
390
|
repo.ui.status(_('merging %s and %s to %s\n')
|
|
391
|
% (lfutil.splitstandin(orig),
|
|
391
|
% (lfutil.splitstandin(orig),
|
|
392
|
lfutil.splitstandin(fcother.path()),
|
|
392
|
lfutil.splitstandin(fcother.path()),
|
|
393
|
lfutil.splitstandin(fcdest.path())))
|
|
393
|
lfutil.splitstandin(fcdest.path())))
|
|
394
|
else:
|
|
394
|
else:
|
|
395
|
repo.ui.status(_('merging %s\n')
|
|
395
|
repo.ui.status(_('merging %s\n')
|
|
396
|
% lfutil.splitstandin(fcdest.path()))
|
|
396
|
% lfutil.splitstandin(fcdest.path()))
|
|
397
|
|
|
397
|
|
|
398
|
if fcancestor.path() != fcother.path() and fcother.data() == \
|
|
398
|
if fcancestor.path() != fcother.path() and fcother.data() == \
|
|
399
|
fcancestor.data():
|
|
399
|
fcancestor.data():
|
|
400
|
return 0
|
|
400
|
return 0
|
|
401
|
if fcancestor.path() != fcdest.path() and fcdest.data() == \
|
|
401
|
if fcancestor.path() != fcdest.path() and fcdest.data() == \
|
|
402
|
fcancestor.data():
|
|
402
|
fcancestor.data():
|
|
403
|
repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
|
|
403
|
repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
|
|
404
|
return 0
|
|
404
|
return 0
|
|
405
|
|
|
405
|
|
|
406
|
if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
|
|
406
|
if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
|
|
407
|
'keep (l)ocal or take (o)ther?') %
|
|
407
|
'keep (l)ocal or take (o)ther?') %
|
|
408
|
lfutil.splitstandin(orig),
|
|
408
|
lfutil.splitstandin(orig),
|
|
409
|
(_('&Local'), _('&Other')), 0) == 0:
|
|
409
|
(_('&Local'), _('&Other')), 0) == 0:
|
|
410
|
return 0
|
|
410
|
return 0
|
|
411
|
else:
|
|
411
|
else:
|
|
412
|
repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
|
|
412
|
repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
|
|
413
|
return 0
|
|
413
|
return 0
|
|
414
|
|
|
414
|
|
|
415
|
# Copy first changes the matchers to match standins instead of
|
|
415
|
# Copy first changes the matchers to match standins instead of
|
|
416
|
# largefiles. Then it overrides util.copyfile in that function it
|
|
416
|
# largefiles. Then it overrides util.copyfile in that function it
|
|
417
|
# checks if the destination largefile already exists. It also keeps a
|
|
417
|
# checks if the destination largefile already exists. It also keeps a
|
|
418
|
# list of copied files so that the largefiles can be copied and the
|
|
418
|
# list of copied files so that the largefiles can be copied and the
|
|
419
|
# dirstate updated.
|
|
419
|
# dirstate updated.
|
|
420
|
def overridecopy(orig, ui, repo, pats, opts, rename=False):
|
|
420
|
def overridecopy(orig, ui, repo, pats, opts, rename=False):
|
|
421
|
# doesn't remove largefile on rename
|
|
421
|
# doesn't remove largefile on rename
|
|
422
|
if len(pats) < 2:
|
|
422
|
if len(pats) < 2:
|
|
423
|
# this isn't legal, let the original function deal with it
|
|
423
|
# this isn't legal, let the original function deal with it
|
|
424
|
return orig(ui, repo, pats, opts, rename)
|
|
424
|
return orig(ui, repo, pats, opts, rename)
|
|
425
|
|
|
425
|
|
|
426
|
def makestandin(relpath):
|
|
426
|
def makestandin(relpath):
|
|
427
|
path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
|
|
427
|
path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
|
|
428
|
return os.path.join(repo.wjoin(lfutil.standin(path)))
|
|
428
|
return os.path.join(repo.wjoin(lfutil.standin(path)))
|
|
429
|
|
|
429
|
|
|
430
|
fullpats = scmutil.expandpats(pats)
|
|
430
|
fullpats = scmutil.expandpats(pats)
|
|
431
|
dest = fullpats[-1]
|
|
431
|
dest = fullpats[-1]
|
|
432
|
|
|
432
|
|
|
433
|
if os.path.isdir(dest):
|
|
433
|
if os.path.isdir(dest):
|
|
434
|
if not os.path.isdir(makestandin(dest)):
|
|
434
|
if not os.path.isdir(makestandin(dest)):
|
|
435
|
os.makedirs(makestandin(dest))
|
|
435
|
os.makedirs(makestandin(dest))
|
|
436
|
# This could copy both lfiles and normal files in one command,
|
|
436
|
# This could copy both lfiles and normal files in one command,
|
|
437
|
# but we don't want to do that. First replace their matcher to
|
|
437
|
# but we don't want to do that. First replace their matcher to
|
|
438
|
# only match normal files and run it, then replace it to just
|
|
438
|
# only match normal files and run it, then replace it to just
|
|
439
|
# match largefiles and run it again.
|
|
439
|
# match largefiles and run it again.
|
|
440
|
nonormalfiles = False
|
|
440
|
nonormalfiles = False
|
|
441
|
nolfiles = False
|
|
441
|
nolfiles = False
|
|
442
|
try:
|
|
442
|
try:
|
|
443
|
try:
|
|
443
|
try:
|
|
444
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
444
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
445
|
result = orig(ui, repo, pats, opts, rename)
|
|
445
|
result = orig(ui, repo, pats, opts, rename)
|
|
446
|
except util.Abort, e:
|
|
446
|
except util.Abort, e:
|
|
447
|
if str(e) != _('no files to copy'):
|
|
447
|
if str(e) != _('no files to copy'):
|
|
448
|
raise e
|
|
448
|
raise e
|
|
449
|
else:
|
|
449
|
else:
|
|
450
|
nonormalfiles = True
|
|
450
|
nonormalfiles = True
|
|
451
|
result = 0
|
|
451
|
result = 0
|
|
452
|
finally:
|
|
452
|
finally:
|
|
453
|
restorematchfn()
|
|
453
|
restorematchfn()
|
|
454
|
|
|
454
|
|
|
455
|
# The first rename can cause our current working directory to be removed.
|
|
455
|
# The first rename can cause our current working directory to be removed.
|
|
456
|
# In that case there is nothing left to copy/rename so just quit.
|
|
456
|
# In that case there is nothing left to copy/rename so just quit.
|
|
457
|
try:
|
|
457
|
try:
|
|
458
|
repo.getcwd()
|
|
458
|
repo.getcwd()
|
|
459
|
except OSError:
|
|
459
|
except OSError:
|
|
460
|
return result
|
|
460
|
return result
|
|
461
|
|
|
461
|
|
|
462
|
try:
|
|
462
|
try:
|
|
463
|
try:
|
|
463
|
try:
|
|
464
|
# When we call orig below it creates the standins but we don't add
|
|
464
|
# When we call orig below it creates the standins but we don't add
|
|
465
|
# them to the dir state until later so lock during that time.
|
|
465
|
# them to the dir state until later so lock during that time.
|
|
466
|
wlock = repo.wlock()
|
|
466
|
wlock = repo.wlock()
|
|
467
|
|
|
467
|
|
|
468
|
manifest = repo[None].manifest()
|
|
468
|
manifest = repo[None].manifest()
|
|
469
|
oldmatch = None # for the closure
|
|
469
|
oldmatch = None # for the closure
|
|
470
|
def overridematch(ctx, pats=[], opts={}, globbed=False,
|
|
470
|
def overridematch(ctx, pats=[], opts={}, globbed=False,
|
|
471
|
default='relpath'):
|
|
471
|
default='relpath'):
|
|
472
|
newpats = []
|
|
472
|
newpats = []
|
|
473
|
# The patterns were previously mangled to add the standin
|
|
473
|
# The patterns were previously mangled to add the standin
|
|
474
|
# directory; we need to remove that now
|
|
474
|
# directory; we need to remove that now
|
|
475
|
for pat in pats:
|
|
475
|
for pat in pats:
|
|
476
|
if match_.patkind(pat) is None and lfutil.shortname in pat:
|
|
476
|
if match_.patkind(pat) is None and lfutil.shortname in pat:
|
|
477
|
newpats.append(pat.replace(lfutil.shortname, ''))
|
|
477
|
newpats.append(pat.replace(lfutil.shortname, ''))
|
|
478
|
else:
|
|
478
|
else:
|
|
479
|
newpats.append(pat)
|
|
479
|
newpats.append(pat)
|
|
480
|
match = oldmatch(ctx, newpats, opts, globbed, default)
|
|
480
|
match = oldmatch(ctx, newpats, opts, globbed, default)
|
|
481
|
m = copy.copy(match)
|
|
481
|
m = copy.copy(match)
|
|
482
|
lfile = lambda f: lfutil.standin(f) in manifest
|
|
482
|
lfile = lambda f: lfutil.standin(f) in manifest
|
|
483
|
m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
|
|
483
|
m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
|
|
484
|
m._fmap = set(m._files)
|
|
484
|
m._fmap = set(m._files)
|
|
485
|
origmatchfn = m.matchfn
|
|
485
|
origmatchfn = m.matchfn
|
|
486
|
m.matchfn = lambda f: (lfutil.isstandin(f) and
|
|
486
|
m.matchfn = lambda f: (lfutil.isstandin(f) and
|
|
487
|
(f in manifest) and
|
|
487
|
(f in manifest) and
|
|
488
|
origmatchfn(lfutil.splitstandin(f)) or
|
|
488
|
origmatchfn(lfutil.splitstandin(f)) or
|
|
489
|
None)
|
|
489
|
None)
|
|
490
|
return m
|
|
490
|
return m
|
|
491
|
oldmatch = installmatchfn(overridematch)
|
|
491
|
oldmatch = installmatchfn(overridematch)
|
|
492
|
listpats = []
|
|
492
|
listpats = []
|
|
493
|
for pat in pats:
|
|
493
|
for pat in pats:
|
|
494
|
if match_.patkind(pat) is not None:
|
|
494
|
if match_.patkind(pat) is not None:
|
|
495
|
listpats.append(pat)
|
|
495
|
listpats.append(pat)
|
|
496
|
else:
|
|
496
|
else:
|
|
497
|
listpats.append(makestandin(pat))
|
|
497
|
listpats.append(makestandin(pat))
|
|
498
|
|
|
498
|
|
|
499
|
try:
|
|
499
|
try:
|
|
500
|
origcopyfile = util.copyfile
|
|
500
|
origcopyfile = util.copyfile
|
|
501
|
copiedfiles = []
|
|
501
|
copiedfiles = []
|
|
502
|
def overridecopyfile(src, dest):
|
|
502
|
def overridecopyfile(src, dest):
|
|
503
|
if (lfutil.shortname in src and
|
|
503
|
if (lfutil.shortname in src and
|
|
504
|
dest.startswith(repo.wjoin(lfutil.shortname))):
|
|
504
|
dest.startswith(repo.wjoin(lfutil.shortname))):
|
|
505
|
destlfile = dest.replace(lfutil.shortname, '')
|
|
505
|
destlfile = dest.replace(lfutil.shortname, '')
|
|
506
|
if not opts['force'] and os.path.exists(destlfile):
|
|
506
|
if not opts['force'] and os.path.exists(destlfile):
|
|
507
|
raise IOError('',
|
|
507
|
raise IOError('',
|
|
508
|
_('destination largefile already exists'))
|
|
508
|
_('destination largefile already exists'))
|
|
509
|
copiedfiles.append((src, dest))
|
|
509
|
copiedfiles.append((src, dest))
|
|
510
|
origcopyfile(src, dest)
|
|
510
|
origcopyfile(src, dest)
|
|
511
|
|
|
511
|
|
|
512
|
util.copyfile = overridecopyfile
|
|
512
|
util.copyfile = overridecopyfile
|
|
513
|
result += orig(ui, repo, listpats, opts, rename)
|
|
513
|
result += orig(ui, repo, listpats, opts, rename)
|
|
514
|
finally:
|
|
514
|
finally:
|
|
515
|
util.copyfile = origcopyfile
|
|
515
|
util.copyfile = origcopyfile
|
|
516
|
|
|
516
|
|
|
517
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
517
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
518
|
for (src, dest) in copiedfiles:
|
|
518
|
for (src, dest) in copiedfiles:
|
|
519
|
if (lfutil.shortname in src and
|
|
519
|
if (lfutil.shortname in src and
|
|
520
|
dest.startswith(repo.wjoin(lfutil.shortname))):
|
|
520
|
dest.startswith(repo.wjoin(lfutil.shortname))):
|
|
521
|
srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
|
|
521
|
srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
|
|
522
|
destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
|
|
522
|
destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
|
|
523
|
destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
|
|
523
|
destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
|
|
524
|
if not os.path.isdir(destlfiledir):
|
|
524
|
if not os.path.isdir(destlfiledir):
|
|
525
|
os.makedirs(destlfiledir)
|
|
525
|
os.makedirs(destlfiledir)
|
|
526
|
if rename:
|
|
526
|
if rename:
|
|
527
|
os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
|
|
527
|
os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
|
|
528
|
lfdirstate.remove(srclfile)
|
|
528
|
lfdirstate.remove(srclfile)
|
|
529
|
else:
|
|
529
|
else:
|
|
530
|
util.copyfile(repo.wjoin(srclfile),
|
|
530
|
util.copyfile(repo.wjoin(srclfile),
|
|
531
|
repo.wjoin(destlfile))
|
|
531
|
repo.wjoin(destlfile))
|
|
532
|
|
|
532
|
|
|
533
|
lfdirstate.add(destlfile)
|
|
533
|
lfdirstate.add(destlfile)
|
|
534
|
lfdirstate.write()
|
|
534
|
lfdirstate.write()
|
|
535
|
except util.Abort, e:
|
|
535
|
except util.Abort, e:
|
|
536
|
if str(e) != _('no files to copy'):
|
|
536
|
if str(e) != _('no files to copy'):
|
|
537
|
raise e
|
|
537
|
raise e
|
|
538
|
else:
|
|
538
|
else:
|
|
539
|
nolfiles = True
|
|
539
|
nolfiles = True
|
|
540
|
finally:
|
|
540
|
finally:
|
|
541
|
restorematchfn()
|
|
541
|
restorematchfn()
|
|
542
|
wlock.release()
|
|
542
|
wlock.release()
|
|
543
|
|
|
543
|
|
|
544
|
if nolfiles and nonormalfiles:
|
|
544
|
if nolfiles and nonormalfiles:
|
|
545
|
raise util.Abort(_('no files to copy'))
|
|
545
|
raise util.Abort(_('no files to copy'))
|
|
546
|
|
|
546
|
|
|
547
|
return result
|
|
547
|
return result
|
|
548
|
|
|
548
|
|
|
549
|
# When the user calls revert, we have to be careful to not revert any
|
|
549
|
# When the user calls revert, we have to be careful to not revert any
|
|
550
|
# changes to other largefiles accidentally. This means we have to keep
|
|
550
|
# changes to other largefiles accidentally. This means we have to keep
|
|
551
|
# track of the largefiles that are being reverted so we only pull down
|
|
551
|
# track of the largefiles that are being reverted so we only pull down
|
|
552
|
# the necessary largefiles.
|
|
552
|
# the necessary largefiles.
|
|
553
|
#
|
|
553
|
#
|
|
554
|
# Standins are only updated (to match the hash of largefiles) before
|
|
554
|
# Standins are only updated (to match the hash of largefiles) before
|
|
555
|
# commits. Update the standins then run the original revert, changing
|
|
555
|
# commits. Update the standins then run the original revert, changing
|
|
556
|
# the matcher to hit standins instead of largefiles. Based on the
|
|
556
|
# the matcher to hit standins instead of largefiles. Based on the
|
|
557
|
# resulting standins update the largefiles. Then return the standins
|
|
557
|
# resulting standins update the largefiles. Then return the standins
|
|
558
|
# to their proper state
|
|
558
|
# to their proper state
|
|
559
|
def overriderevert(orig, ui, repo, *pats, **opts):
|
|
559
|
def overriderevert(orig, ui, repo, *pats, **opts):
|
|
560
|
# Because we put the standins in a bad state (by updating them)
|
|
560
|
# Because we put the standins in a bad state (by updating them)
|
|
561
|
# and then return them to a correct state we need to lock to
|
|
561
|
# and then return them to a correct state we need to lock to
|
|
562
|
# prevent others from changing them in their incorrect state.
|
|
562
|
# prevent others from changing them in their incorrect state.
|
|
563
|
wlock = repo.wlock()
|
|
563
|
wlock = repo.wlock()
|
|
564
|
try:
|
|
564
|
try:
|
|
565
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
565
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
566
|
(modified, added, removed, missing, unknown, ignored, clean) = \
|
|
566
|
(modified, added, removed, missing, unknown, ignored, clean) = \
|
|
567
|
lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
|
|
567
|
lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
|
|
568
|
for lfile in modified:
|
|
568
|
for lfile in modified:
|
|
569
|
lfutil.updatestandin(repo, lfutil.standin(lfile))
|
|
569
|
lfutil.updatestandin(repo, lfutil.standin(lfile))
|
|
570
|
for lfile in missing:
|
|
570
|
for lfile in missing:
|
|
571
|
if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
|
|
571
|
if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
|
|
572
|
os.unlink(repo.wjoin(lfutil.standin(lfile)))
|
|
572
|
os.unlink(repo.wjoin(lfutil.standin(lfile)))
|
|
573
|
|
|
573
|
|
|
574
|
try:
|
|
574
|
try:
|
|
575
|
ctx = scmutil.revsingle(repo, opts.get('rev'))
|
|
575
|
ctx = scmutil.revsingle(repo, opts.get('rev'))
|
|
576
|
oldmatch = None # for the closure
|
|
576
|
oldmatch = None # for the closure
|
|
577
|
def overridematch(ctx, pats=[], opts={}, globbed=False,
|
|
577
|
def overridematch(ctx, pats=[], opts={}, globbed=False,
|
|
578
|
default='relpath'):
|
|
578
|
default='relpath'):
|
|
579
|
match = oldmatch(ctx, pats, opts, globbed, default)
|
|
579
|
match = oldmatch(ctx, pats, opts, globbed, default)
|
|
580
|
m = copy.copy(match)
|
|
580
|
m = copy.copy(match)
|
|
581
|
def tostandin(f):
|
|
581
|
def tostandin(f):
|
|
582
|
if lfutil.standin(f) in ctx:
|
|
582
|
if lfutil.standin(f) in ctx:
|
|
583
|
return lfutil.standin(f)
|
|
583
|
return lfutil.standin(f)
|
|
584
|
elif lfutil.standin(f) in repo[None]:
|
|
584
|
elif lfutil.standin(f) in repo[None]:
|
|
585
|
return None
|
|
585
|
return None
|
|
586
|
return f
|
|
586
|
return f
|
|
587
|
m._files = [tostandin(f) for f in m._files]
|
|
587
|
m._files = [tostandin(f) for f in m._files]
|
|
588
|
m._files = [f for f in m._files if f is not None]
|
|
588
|
m._files = [f for f in m._files if f is not None]
|
|
589
|
m._fmap = set(m._files)
|
|
589
|
m._fmap = set(m._files)
|
|
590
|
origmatchfn = m.matchfn
|
|
590
|
origmatchfn = m.matchfn
|
|
591
|
def matchfn(f):
|
|
591
|
def matchfn(f):
|
|
592
|
if lfutil.isstandin(f):
|
|
592
|
if lfutil.isstandin(f):
|
|
593
|
# We need to keep track of what largefiles are being
|
|
593
|
# We need to keep track of what largefiles are being
|
|
594
|
# matched so we know which ones to update later --
|
|
594
|
# matched so we know which ones to update later --
|
|
595
|
# otherwise we accidentally revert changes to other
|
|
595
|
# otherwise we accidentally revert changes to other
|
|
596
|
# largefiles. This is repo-specific, so duckpunch the
|
|
596
|
# largefiles. This is repo-specific, so duckpunch the
|
|
597
|
# repo object to keep the list of largefiles for us
|
|
597
|
# repo object to keep the list of largefiles for us
|
|
598
|
# later.
|
|
598
|
# later.
|
|
599
|
if origmatchfn(lfutil.splitstandin(f)) and \
|
|
599
|
if origmatchfn(lfutil.splitstandin(f)) and \
|
|
600
|
(f in repo[None] or f in ctx):
|
|
600
|
(f in repo[None] or f in ctx):
|
|
601
|
lfileslist = getattr(repo, '_lfilestoupdate', [])
|
|
601
|
lfileslist = getattr(repo, '_lfilestoupdate', [])
|
|
602
|
lfileslist.append(lfutil.splitstandin(f))
|
|
602
|
lfileslist.append(lfutil.splitstandin(f))
|
|
603
|
repo._lfilestoupdate = lfileslist
|
|
603
|
repo._lfilestoupdate = lfileslist
|
|
604
|
return True
|
|
604
|
return True
|
|
605
|
else:
|
|
605
|
else:
|
|
606
|
return False
|
|
606
|
return False
|
|
607
|
return origmatchfn(f)
|
|
607
|
return origmatchfn(f)
|
|
608
|
m.matchfn = matchfn
|
|
608
|
m.matchfn = matchfn
|
|
609
|
return m
|
|
609
|
return m
|
|
610
|
oldmatch = installmatchfn(overridematch)
|
|
610
|
oldmatch = installmatchfn(overridematch)
|
|
611
|
scmutil.match
|
|
611
|
scmutil.match
|
|
612
|
matches = overridematch(repo[None], pats, opts)
|
|
612
|
matches = overridematch(repo[None], pats, opts)
|
|
613
|
orig(ui, repo, *pats, **opts)
|
|
613
|
orig(ui, repo, *pats, **opts)
|
|
614
|
finally:
|
|
614
|
finally:
|
|
615
|
restorematchfn()
|
|
615
|
restorematchfn()
|
|
616
|
lfileslist = getattr(repo, '_lfilestoupdate', [])
|
|
616
|
lfileslist = getattr(repo, '_lfilestoupdate', [])
|
|
617
|
lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
|
|
617
|
lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
|
|
618
|
printmessage=False)
|
|
618
|
printmessage=False)
|
|
619
|
|
|
619
|
|
|
620
|
# empty out the largefiles list so we start fresh next time
|
|
620
|
# empty out the largefiles list so we start fresh next time
|
|
621
|
repo._lfilestoupdate = []
|
|
621
|
repo._lfilestoupdate = []
|
|
622
|
for lfile in modified:
|
|
622
|
for lfile in modified:
|
|
623
|
if lfile in lfileslist:
|
|
623
|
if lfile in lfileslist:
|
|
624
|
if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
|
|
624
|
if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
|
|
625
|
in repo['.']:
|
|
625
|
in repo['.']:
|
|
626
|
lfutil.writestandin(repo, lfutil.standin(lfile),
|
|
626
|
lfutil.writestandin(repo, lfutil.standin(lfile),
|
|
627
|
repo['.'][lfile].data().strip(),
|
|
627
|
repo['.'][lfile].data().strip(),
|
|
628
|
'x' in repo['.'][lfile].flags())
|
|
628
|
'x' in repo['.'][lfile].flags())
|
|
629
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
629
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
630
|
for lfile in added:
|
|
630
|
for lfile in added:
|
|
631
|
standin = lfutil.standin(lfile)
|
|
631
|
standin = lfutil.standin(lfile)
|
|
632
|
if standin not in ctx and (standin in matches or opts.get('all')):
|
|
632
|
if standin not in ctx and (standin in matches or opts.get('all')):
|
|
633
|
if lfile in lfdirstate:
|
|
633
|
if lfile in lfdirstate:
|
|
634
|
lfdirstate.drop(lfile)
|
|
634
|
lfdirstate.drop(lfile)
|
|
635
|
util.unlinkpath(repo.wjoin(standin))
|
|
635
|
util.unlinkpath(repo.wjoin(standin))
|
|
636
|
lfdirstate.write()
|
|
636
|
lfdirstate.write()
|
|
637
|
finally:
|
|
637
|
finally:
|
|
638
|
wlock.release()
|
|
638
|
wlock.release()
|
|
639
|
|
|
639
|
|
|
640
|
def hgupdate(orig, repo, node):
|
|
640
|
def hgupdate(orig, repo, node):
|
|
641
|
# Only call updatelfiles the standins that have changed to save time
|
|
641
|
# Only call updatelfiles the standins that have changed to save time
|
|
642
|
oldstandins = lfutil.getstandinsstate(repo)
|
|
642
|
oldstandins = lfutil.getstandinsstate(repo)
|
|
643
|
result = orig(repo, node)
|
|
643
|
result = orig(repo, node)
|
|
644
|
newstandins = lfutil.getstandinsstate(repo)
|
|
644
|
newstandins = lfutil.getstandinsstate(repo)
|
|
645
|
filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
|
|
645
|
filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
|
|
646
|
lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
|
|
646
|
lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
|
|
647
|
return result
|
|
647
|
return result
|
|
648
|
|
|
648
|
|
|
649
|
def hgclean(orig, repo, node, show_stats=True):
|
|
649
|
def hgclean(orig, repo, node, show_stats=True):
|
|
650
|
result = orig(repo, node, show_stats)
|
|
650
|
result = orig(repo, node, show_stats)
|
|
651
|
lfcommands.updatelfiles(repo.ui, repo)
|
|
651
|
lfcommands.updatelfiles(repo.ui, repo)
|
|
652
|
return result
|
|
652
|
return result
|
|
653
|
|
|
653
|
|
|
654
|
def hgmerge(orig, repo, node, force=None, remind=True):
|
|
654
|
def hgmerge(orig, repo, node, force=None, remind=True):
|
|
655
|
# Mark the repo as being in the middle of a merge, so that
|
|
655
|
# Mark the repo as being in the middle of a merge, so that
|
|
656
|
# updatelfiles() will know that it needs to trust the standins in
|
|
656
|
# updatelfiles() will know that it needs to trust the standins in
|
|
657
|
# the working copy, not in the standins in the current node
|
|
657
|
# the working copy, not in the standins in the current node
|
|
658
|
repo._ismerging = True
|
|
658
|
repo._ismerging = True
|
|
659
|
try:
|
|
659
|
try:
|
|
660
|
result = orig(repo, node, force, remind)
|
|
660
|
result = orig(repo, node, force, remind)
|
|
661
|
lfcommands.updatelfiles(repo.ui, repo)
|
|
661
|
lfcommands.updatelfiles(repo.ui, repo)
|
|
662
|
finally:
|
|
662
|
finally:
|
|
663
|
repo._ismerging = False
|
|
663
|
repo._ismerging = False
|
|
664
|
return result
|
|
664
|
return result
|
|
665
|
|
|
665
|
|
|
666
|
# When we rebase a repository with remotely changed largefiles, we need to
|
|
666
|
# When we rebase a repository with remotely changed largefiles, we need to
|
|
667
|
# take some extra care so that the largefiles are correctly updated in the
|
|
667
|
# take some extra care so that the largefiles are correctly updated in the
|
|
668
|
# working copy
|
|
668
|
# working copy
|
|
669
|
def overridepull(orig, ui, repo, source=None, **opts):
|
|
669
|
def overridepull(orig, ui, repo, source=None, **opts):
|
|
670
|
revsprepull = len(repo)
|
|
670
|
revsprepull = len(repo)
|
|
671
|
if opts.get('rebase', False):
|
|
671
|
if opts.get('rebase', False):
|
|
672
|
repo._isrebasing = True
|
|
672
|
repo._isrebasing = True
|
|
673
|
try:
|
|
673
|
try:
|
|
674
|
if opts.get('update'):
|
|
674
|
if opts.get('update'):
|
|
675
|
del opts['update']
|
|
675
|
del opts['update']
|
|
676
|
ui.debug('--update and --rebase are not compatible, ignoring '
|
|
676
|
ui.debug('--update and --rebase are not compatible, ignoring '
|
|
677
|
'the update flag\n')
|
|
677
|
'the update flag\n')
|
|
678
|
del opts['rebase']
|
|
678
|
del opts['rebase']
|
|
679
|
cmdutil.bailifchanged(repo)
|
|
679
|
cmdutil.bailifchanged(repo)
|
|
680
|
origpostincoming = commands.postincoming
|
|
680
|
origpostincoming = commands.postincoming
|
|
681
|
def _dummy(*args, **kwargs):
|
|
681
|
def _dummy(*args, **kwargs):
|
|
682
|
pass
|
|
682
|
pass
|
|
683
|
commands.postincoming = _dummy
|
|
683
|
commands.postincoming = _dummy
|
|
684
|
repo.lfpullsource = source
|
|
684
|
repo.lfpullsource = source
|
|
685
|
if not source:
|
|
685
|
if not source:
|
|
686
|
source = 'default'
|
|
686
|
source = 'default'
|
|
687
|
try:
|
|
687
|
try:
|
|
688
|
result = commands.pull(ui, repo, source, **opts)
|
|
688
|
result = commands.pull(ui, repo, source, **opts)
|
|
689
|
finally:
|
|
689
|
finally:
|
|
690
|
commands.postincoming = origpostincoming
|
|
690
|
commands.postincoming = origpostincoming
|
|
691
|
revspostpull = len(repo)
|
|
691
|
revspostpull = len(repo)
|
|
692
|
if revspostpull > revsprepull:
|
|
692
|
if revspostpull > revsprepull:
|
|
693
|
result = result or rebase.rebase(ui, repo)
|
|
693
|
result = result or rebase.rebase(ui, repo)
|
|
694
|
finally:
|
|
694
|
finally:
|
|
695
|
repo._isrebasing = False
|
|
695
|
repo._isrebasing = False
|
|
696
|
else:
|
|
696
|
else:
|
|
697
|
repo.lfpullsource = source
|
|
697
|
repo.lfpullsource = source
|
|
698
|
if not source:
|
|
698
|
if not source:
|
|
699
|
source = 'default'
|
|
699
|
source = 'default'
|
|
700
|
oldheads = lfutil.getcurrentheads(repo)
|
|
700
|
oldheads = lfutil.getcurrentheads(repo)
|
|
701
|
result = orig(ui, repo, source, **opts)
|
|
701
|
result = orig(ui, repo, source, **opts)
|
|
702
|
# If we do not have the new largefiles for any new heads we pulled, we
|
|
702
|
# If we do not have the new largefiles for any new heads we pulled, we
|
|
703
|
# will run into a problem later if we try to merge or rebase with one of
|
|
703
|
# will run into a problem later if we try to merge or rebase with one of
|
|
704
|
# these heads, so cache the largefiles now directly into the system
|
|
704
|
# these heads, so cache the largefiles now directly into the system
|
|
705
|
# cache.
|
|
705
|
# cache.
|
|
706
|
ui.status(_("caching new largefiles\n"))
|
|
706
|
ui.status(_("caching new largefiles\n"))
|
|
707
|
numcached = 0
|
|
707
|
numcached = 0
|
|
708
|
heads = lfutil.getcurrentheads(repo)
|
|
708
|
heads = lfutil.getcurrentheads(repo)
|
|
709
|
newheads = set(heads).difference(set(oldheads))
|
|
709
|
newheads = set(heads).difference(set(oldheads))
|
|
710
|
for head in newheads:
|
|
710
|
for head in newheads:
|
|
711
|
(cached, missing) = lfcommands.cachelfiles(ui, repo, head)
|
|
711
|
(cached, missing) = lfcommands.cachelfiles(ui, repo, head)
|
|
712
|
numcached += len(cached)
|
|
712
|
numcached += len(cached)
|
|
713
|
ui.status(_("%d largefiles cached\n") % numcached)
|
|
713
|
ui.status(_("%d largefiles cached\n") % numcached)
|
|
714
|
if opts.get('all_largefiles'):
|
|
714
|
if opts.get('all_largefiles'):
|
|
715
|
revspostpull = len(repo)
|
|
715
|
revspostpull = len(repo)
|
|
716
|
revs = []
|
|
716
|
revs = []
|
|
717
|
for rev in xrange(revsprepull + 1, revspostpull):
|
|
717
|
for rev in xrange(revsprepull + 1, revspostpull):
|
|
718
|
revs.append(repo[rev].rev())
|
|
718
|
revs.append(repo[rev].rev())
|
|
719
|
lfcommands.downloadlfiles(ui, repo, revs)
|
|
719
|
lfcommands.downloadlfiles(ui, repo, revs)
|
|
720
|
return result
|
|
720
|
return result
|
|
721
|
|
|
721
|
|
|
722
|
def overrideclone(orig, ui, source, dest=None, **opts):
|
|
722
|
def overrideclone(orig, ui, source, dest=None, **opts):
|
|
723
|
d = dest
|
|
723
|
d = dest
|
|
724
|
if d is None:
|
|
724
|
if d is None:
|
|
725
|
d = hg.defaultdest(source)
|
|
725
|
d = hg.defaultdest(source)
|
|
726
|
if opts.get('all_largefiles') and not hg.islocal(d):
|
|
726
|
if opts.get('all_largefiles') and not hg.islocal(d):
|
|
727
|
raise util.Abort(_(
|
|
727
|
raise util.Abort(_(
|
|
728
|
'--all-largefiles is incompatible with non-local destination %s' %
|
|
728
|
'--all-largefiles is incompatible with non-local destination %s' %
|
|
729
|
d))
|
|
729
|
d))
|
|
730
|
|
|
730
|
|
|
731
|
return orig(ui, source, dest, **opts)
|
|
731
|
return orig(ui, source, dest, **opts)
|
|
732
|
|
|
732
|
|
|
733
|
def hgclone(orig, ui, opts, *args, **kwargs):
|
|
733
|
def hgclone(orig, ui, opts, *args, **kwargs):
|
|
734
|
result = orig(ui, opts, *args, **kwargs)
|
|
734
|
result = orig(ui, opts, *args, **kwargs)
|
|
735
|
|
|
735
|
|
|
736
|
if result is not None and opts.get('all_largefiles'):
|
|
736
|
if result is not None and opts.get('all_largefiles'):
|
|
737
|
sourcerepo, destrepo = result
|
|
737
|
sourcerepo, destrepo = result
|
|
738
|
repo = destrepo.local()
|
|
738
|
repo = destrepo.local()
|
|
739
|
|
|
739
|
|
|
740
|
# The .hglf directory must exist for the standin matcher to match
|
|
740
|
# The .hglf directory must exist for the standin matcher to match
|
|
741
|
# anything (which listlfiles uses for each rev), and .hg/largefiles is
|
|
741
|
# anything (which listlfiles uses for each rev), and .hg/largefiles is
|
|
742
|
# assumed to exist by the code that caches the downloaded file. These
|
|
742
|
# assumed to exist by the code that caches the downloaded file. These
|
|
743
|
# directories exist if clone updated to any rev.
|
|
743
|
# directories exist if clone updated to any rev.
|
|
744
|
if opts.get('noupdate'):
|
|
744
|
if opts.get('noupdate'):
|
|
745
|
util.makedirs(repo.pathto(lfutil.shortname))
|
|
745
|
util.makedirs(repo.pathto(lfutil.shortname))
|
|
746
|
util.makedirs(repo.join(lfutil.longname))
|
|
746
|
util.makedirs(repo.join(lfutil.longname))
|
|
747
|
|
|
747
|
|
|
748
|
# Caching is implicitly limited to 'rev' option, since the dest repo was
|
|
748
|
# Caching is implicitly limited to 'rev' option, since the dest repo was
|
|
749
|
# truncated at that point.
|
|
749
|
# truncated at that point.
|
|
750
|
success, missing = lfcommands.downloadlfiles(ui, repo, None)
|
|
750
|
success, missing = lfcommands.downloadlfiles(ui, repo, None)
|
|
751
|
|
|
751
|
|
|
752
|
if missing != 0:
|
|
752
|
if missing != 0:
|
|
753
|
return None
|
|
753
|
return None
|
|
754
|
|
|
754
|
|
|
755
|
return result
|
|
755
|
return result
|
|
756
|
|
|
756
|
|
|
757
|
def overriderebase(orig, ui, repo, **opts):
|
|
757
|
def overriderebase(orig, ui, repo, **opts):
|
|
758
|
repo._isrebasing = True
|
|
758
|
repo._isrebasing = True
|
|
759
|
try:
|
|
759
|
try:
|
|
760
|
return orig(ui, repo, **opts)
|
|
760
|
return orig(ui, repo, **opts)
|
|
761
|
finally:
|
|
761
|
finally:
|
|
762
|
repo._isrebasing = False
|
|
762
|
repo._isrebasing = False
|
|
763
|
|
|
763
|
|
|
764
|
def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
|
|
764
|
def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
|
|
765
|
prefix=None, mtime=None, subrepos=None):
|
|
765
|
prefix=None, mtime=None, subrepos=None):
|
|
766
|
# No need to lock because we are only reading history and
|
|
766
|
# No need to lock because we are only reading history and
|
|
767
|
# largefile caches, neither of which are modified.
|
|
767
|
# largefile caches, neither of which are modified.
|
|
768
|
lfcommands.cachelfiles(repo.ui, repo, node)
|
|
768
|
lfcommands.cachelfiles(repo.ui, repo, node)
|
|
769
|
|
|
769
|
|
|
770
|
if kind not in archival.archivers:
|
|
770
|
if kind not in archival.archivers:
|
|
771
|
raise util.Abort(_("unknown archive type '%s'") % kind)
|
|
771
|
raise util.Abort(_("unknown archive type '%s'") % kind)
|
|
772
|
|
|
772
|
|
|
773
|
ctx = repo[node]
|
|
773
|
ctx = repo[node]
|
|
774
|
|
|
774
|
|
|
775
|
if kind == 'files':
|
|
775
|
if kind == 'files':
|
|
776
|
if prefix:
|
|
776
|
if prefix:
|
|
777
|
raise util.Abort(
|
|
777
|
raise util.Abort(
|
|
778
|
_('cannot give prefix when archiving to files'))
|
|
778
|
_('cannot give prefix when archiving to files'))
|
|
779
|
else:
|
|
779
|
else:
|
|
780
|
prefix = archival.tidyprefix(dest, kind, prefix)
|
|
780
|
prefix = archival.tidyprefix(dest, kind, prefix)
|
|
781
|
|
|
781
|
|
|
782
|
def write(name, mode, islink, getdata):
|
|
782
|
def write(name, mode, islink, getdata):
|
|
783
|
if matchfn and not matchfn(name):
|
|
783
|
if matchfn and not matchfn(name):
|
|
784
|
return
|
|
784
|
return
|
|
785
|
data = getdata()
|
|
785
|
data = getdata()
|
|
786
|
if decode:
|
|
786
|
if decode:
|
|
787
|
data = repo.wwritedata(name, data)
|
|
787
|
data = repo.wwritedata(name, data)
|
|
788
|
archiver.addfile(prefix + name, mode, islink, data)
|
|
788
|
archiver.addfile(prefix + name, mode, islink, data)
|
|
789
|
|
|
789
|
|
|
790
|
archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
|
|
790
|
archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
|
|
791
|
|
|
791
|
|
|
792
|
if repo.ui.configbool("ui", "archivemeta", True):
|
|
792
|
if repo.ui.configbool("ui", "archivemeta", True):
|
|
793
|
def metadata():
|
|
793
|
def metadata():
|
|
794
|
base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
|
|
794
|
base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
|
|
795
|
hex(repo.changelog.node(0)), hex(node), ctx.branch())
|
|
795
|
hex(repo.changelog.node(0)), hex(node), ctx.branch())
|
|
796
|
|
|
796
|
|
|
797
|
tags = ''.join('tag: %s\n' % t for t in ctx.tags()
|
|
797
|
tags = ''.join('tag: %s\n' % t for t in ctx.tags()
|
|
798
|
if repo.tagtype(t) == 'global')
|
|
798
|
if repo.tagtype(t) == 'global')
|
|
799
|
if not tags:
|
|
799
|
if not tags:
|
|
800
|
repo.ui.pushbuffer()
|
|
800
|
repo.ui.pushbuffer()
|
|
801
|
opts = {'template': '{latesttag}\n{latesttagdistance}',
|
|
801
|
opts = {'template': '{latesttag}\n{latesttagdistance}',
|
|
802
|
'style': '', 'patch': None, 'git': None}
|
|
802
|
'style': '', 'patch': None, 'git': None}
|
|
803
|
cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
|
|
803
|
cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
|
|
804
|
ltags, dist = repo.ui.popbuffer().split('\n')
|
|
804
|
ltags, dist = repo.ui.popbuffer().split('\n')
|
|
805
|
tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
|
|
805
|
tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
|
|
806
|
tags += 'latesttagdistance: %s\n' % dist
|
|
806
|
tags += 'latesttagdistance: %s\n' % dist
|
|
807
|
|
|
807
|
|
|
808
|
return base + tags
|
|
808
|
return base + tags
|
|
809
|
|
|
809
|
|
|
810
|
write('.hg_archival.txt', 0644, False, metadata)
|
|
810
|
write('.hg_archival.txt', 0644, False, metadata)
|
|
811
|
|
|
811
|
|
|
812
|
for f in ctx:
|
|
812
|
for f in ctx:
|
|
813
|
ff = ctx.flags(f)
|
|
813
|
ff = ctx.flags(f)
|
|
814
|
getdata = ctx[f].data
|
|
814
|
getdata = ctx[f].data
|
|
815
|
if lfutil.isstandin(f):
|
|
815
|
if lfutil.isstandin(f):
|
|
816
|
path = lfutil.findfile(repo, getdata().strip())
|
|
816
|
path = lfutil.findfile(repo, getdata().strip())
|
|
817
|
if path is None:
|
|
817
|
if path is None:
|
|
818
|
raise util.Abort(
|
|
818
|
raise util.Abort(
|
|
819
|
_('largefile %s not found in repo store or system cache')
|
|
819
|
_('largefile %s not found in repo store or system cache')
|
|
820
|
% lfutil.splitstandin(f))
|
|
820
|
% lfutil.splitstandin(f))
|
|
821
|
f = lfutil.splitstandin(f)
|
|
821
|
f = lfutil.splitstandin(f)
|
|
822
|
|
|
822
|
|
|
823
|
def getdatafn():
|
|
823
|
def getdatafn():
|
|
824
|
fd = None
|
|
824
|
fd = None
|
|
825
|
try:
|
|
825
|
try:
|
|
826
|
fd = open(path, 'rb')
|
|
826
|
fd = open(path, 'rb')
|
|
827
|
return fd.read()
|
|
827
|
return fd.read()
|
|
828
|
finally:
|
|
828
|
finally:
|
|
829
|
if fd:
|
|
829
|
if fd:
|
|
830
|
fd.close()
|
|
830
|
fd.close()
|
|
831
|
|
|
831
|
|
|
832
|
getdata = getdatafn
|
|
832
|
getdata = getdatafn
|
|
833
|
write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
|
|
833
|
write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
|
|
834
|
|
|
834
|
|
|
835
|
if subrepos:
|
|
835
|
if subrepos:
|
|
836
|
for subpath in ctx.substate:
|
|
836
|
for subpath in ctx.substate:
|
|
837
|
sub = ctx.sub(subpath)
|
|
837
|
sub = ctx.sub(subpath)
|
|
838
|
submatch = match_.narrowmatcher(subpath, matchfn)
|
|
838
|
submatch = match_.narrowmatcher(subpath, matchfn)
|
|
839
|
sub.archive(repo.ui, archiver, prefix, submatch)
|
|
839
|
sub.archive(repo.ui, archiver, prefix, submatch)
|
|
840
|
|
|
840
|
|
|
841
|
archiver.done()
|
|
841
|
archiver.done()
|
|
842
|
|
|
842
|
|
|
843
|
def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
|
|
843
|
def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
|
|
|
|
|
844
|
repo._get(repo._state + ('hg',))
|
|
844
|
rev = repo._state[1]
|
|
845
|
rev = repo._state[1]
|
|
845
|
ctx = repo._repo[rev]
|
|
846
|
ctx = repo._repo[rev]
|
|
846
|
|
|
847
|
|
|
847
|
lfcommands.cachelfiles(ui, repo._repo, ctx.node())
|
|
848
|
lfcommands.cachelfiles(ui, repo._repo, ctx.node())
|
|
848
|
|
|
849
|
|
|
849
|
def write(name, mode, islink, getdata):
|
|
850
|
def write(name, mode, islink, getdata):
|
|
850
|
# At this point, the standin has been replaced with the largefile name,
|
|
851
|
# At this point, the standin has been replaced with the largefile name,
|
|
851
|
# so the normal matcher works here without the lfutil variants.
|
|
852
|
# so the normal matcher works here without the lfutil variants.
|
|
852
|
if match and not match(f):
|
|
853
|
if match and not match(f):
|
|
853
|
return
|
|
854
|
return
|
|
854
|
data = getdata()
|
|
855
|
data = getdata()
|
|
855
|
|
|
856
|
|
|
856
|
archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
|
|
857
|
archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
|
|
857
|
|
|
858
|
|
|
858
|
for f in ctx:
|
|
859
|
for f in ctx:
|
|
859
|
ff = ctx.flags(f)
|
|
860
|
ff = ctx.flags(f)
|
|
860
|
getdata = ctx[f].data
|
|
861
|
getdata = ctx[f].data
|
|
861
|
if lfutil.isstandin(f):
|
|
862
|
if lfutil.isstandin(f):
|
|
862
|
path = lfutil.findfile(repo._repo, getdata().strip())
|
|
863
|
path = lfutil.findfile(repo._repo, getdata().strip())
|
|
863
|
if path is None:
|
|
864
|
if path is None:
|
|
864
|
raise util.Abort(
|
|
865
|
raise util.Abort(
|
|
865
|
_('largefile %s not found in repo store or system cache')
|
|
866
|
_('largefile %s not found in repo store or system cache')
|
|
866
|
% lfutil.splitstandin(f))
|
|
867
|
% lfutil.splitstandin(f))
|
|
867
|
f = lfutil.splitstandin(f)
|
|
868
|
f = lfutil.splitstandin(f)
|
|
868
|
|
|
869
|
|
|
869
|
def getdatafn():
|
|
870
|
def getdatafn():
|
|
870
|
fd = None
|
|
871
|
fd = None
|
|
871
|
try:
|
|
872
|
try:
|
|
872
|
fd = open(os.path.join(prefix, path), 'rb')
|
|
873
|
fd = open(os.path.join(prefix, path), 'rb')
|
|
873
|
return fd.read()
|
|
874
|
return fd.read()
|
|
874
|
finally:
|
|
875
|
finally:
|
|
875
|
if fd:
|
|
876
|
if fd:
|
|
876
|
fd.close()
|
|
877
|
fd.close()
|
|
877
|
|
|
878
|
|
|
878
|
getdata = getdatafn
|
|
879
|
getdata = getdatafn
|
|
879
|
|
|
880
|
|
|
880
|
write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
|
|
881
|
write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
|
|
881
|
|
|
882
|
|
|
882
|
for subpath in ctx.substate:
|
|
883
|
for subpath in ctx.substate:
|
|
883
|
sub = ctx.sub(subpath)
|
|
884
|
sub = ctx.sub(subpath)
|
|
884
|
submatch = match_.narrowmatcher(subpath, match)
|
|
885
|
submatch = match_.narrowmatcher(subpath, match)
|
|
885
|
sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
|
|
886
|
sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
|
|
886
|
submatch)
|
|
887
|
submatch)
|
|
887
|
|
|
888
|
|
|
888
|
# If a largefile is modified, the change is not reflected in its
|
|
889
|
# If a largefile is modified, the change is not reflected in its
|
|
889
|
# standin until a commit. cmdutil.bailifchanged() raises an exception
|
|
890
|
# standin until a commit. cmdutil.bailifchanged() raises an exception
|
|
890
|
# if the repo has uncommitted changes. Wrap it to also check if
|
|
891
|
# if the repo has uncommitted changes. Wrap it to also check if
|
|
891
|
# largefiles were changed. This is used by bisect and backout.
|
|
892
|
# largefiles were changed. This is used by bisect and backout.
|
|
892
|
def overridebailifchanged(orig, repo):
|
|
893
|
def overridebailifchanged(orig, repo):
|
|
893
|
orig(repo)
|
|
894
|
orig(repo)
|
|
894
|
repo.lfstatus = True
|
|
895
|
repo.lfstatus = True
|
|
895
|
modified, added, removed, deleted = repo.status()[:4]
|
|
896
|
modified, added, removed, deleted = repo.status()[:4]
|
|
896
|
repo.lfstatus = False
|
|
897
|
repo.lfstatus = False
|
|
897
|
if modified or added or removed or deleted:
|
|
898
|
if modified or added or removed or deleted:
|
|
898
|
raise util.Abort(_('outstanding uncommitted changes'))
|
|
899
|
raise util.Abort(_('outstanding uncommitted changes'))
|
|
899
|
|
|
900
|
|
|
900
|
# Fetch doesn't use cmdutil.bailifchanged so override it to add the check
|
|
901
|
# Fetch doesn't use cmdutil.bailifchanged so override it to add the check
|
|
901
|
def overridefetch(orig, ui, repo, *pats, **opts):
|
|
902
|
def overridefetch(orig, ui, repo, *pats, **opts):
|
|
902
|
repo.lfstatus = True
|
|
903
|
repo.lfstatus = True
|
|
903
|
modified, added, removed, deleted = repo.status()[:4]
|
|
904
|
modified, added, removed, deleted = repo.status()[:4]
|
|
904
|
repo.lfstatus = False
|
|
905
|
repo.lfstatus = False
|
|
905
|
if modified or added or removed or deleted:
|
|
906
|
if modified or added or removed or deleted:
|
|
906
|
raise util.Abort(_('outstanding uncommitted changes'))
|
|
907
|
raise util.Abort(_('outstanding uncommitted changes'))
|
|
907
|
return orig(ui, repo, *pats, **opts)
|
|
908
|
return orig(ui, repo, *pats, **opts)
|
|
908
|
|
|
909
|
|
|
909
|
def overrideforget(orig, ui, repo, *pats, **opts):
|
|
910
|
def overrideforget(orig, ui, repo, *pats, **opts):
|
|
910
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
911
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
911
|
result = orig(ui, repo, *pats, **opts)
|
|
912
|
result = orig(ui, repo, *pats, **opts)
|
|
912
|
restorematchfn()
|
|
913
|
restorematchfn()
|
|
913
|
m = scmutil.match(repo[None], pats, opts)
|
|
914
|
m = scmutil.match(repo[None], pats, opts)
|
|
914
|
|
|
915
|
|
|
915
|
try:
|
|
916
|
try:
|
|
916
|
repo.lfstatus = True
|
|
917
|
repo.lfstatus = True
|
|
917
|
s = repo.status(match=m, clean=True)
|
|
918
|
s = repo.status(match=m, clean=True)
|
|
918
|
finally:
|
|
919
|
finally:
|
|
919
|
repo.lfstatus = False
|
|
920
|
repo.lfstatus = False
|
|
920
|
forget = sorted(s[0] + s[1] + s[3] + s[6])
|
|
921
|
forget = sorted(s[0] + s[1] + s[3] + s[6])
|
|
921
|
forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
|
|
922
|
forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
|
|
922
|
|
|
923
|
|
|
923
|
for f in forget:
|
|
924
|
for f in forget:
|
|
924
|
if lfutil.standin(f) not in repo.dirstate and not \
|
|
925
|
if lfutil.standin(f) not in repo.dirstate and not \
|
|
925
|
os.path.isdir(m.rel(lfutil.standin(f))):
|
|
926
|
os.path.isdir(m.rel(lfutil.standin(f))):
|
|
926
|
ui.warn(_('not removing %s: file is already untracked\n')
|
|
927
|
ui.warn(_('not removing %s: file is already untracked\n')
|
|
927
|
% m.rel(f))
|
|
928
|
% m.rel(f))
|
|
928
|
result = 1
|
|
929
|
result = 1
|
|
929
|
|
|
930
|
|
|
930
|
for f in forget:
|
|
931
|
for f in forget:
|
|
931
|
if ui.verbose or not m.exact(f):
|
|
932
|
if ui.verbose or not m.exact(f):
|
|
932
|
ui.status(_('removing %s\n') % m.rel(f))
|
|
933
|
ui.status(_('removing %s\n') % m.rel(f))
|
|
933
|
|
|
934
|
|
|
934
|
# Need to lock because standin files are deleted then removed from the
|
|
935
|
# Need to lock because standin files are deleted then removed from the
|
|
935
|
# repository and we could race in-between.
|
|
936
|
# repository and we could race in-between.
|
|
936
|
wlock = repo.wlock()
|
|
937
|
wlock = repo.wlock()
|
|
937
|
try:
|
|
938
|
try:
|
|
938
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
939
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
939
|
for f in forget:
|
|
940
|
for f in forget:
|
|
940
|
if lfdirstate[f] == 'a':
|
|
941
|
if lfdirstate[f] == 'a':
|
|
941
|
lfdirstate.drop(f)
|
|
942
|
lfdirstate.drop(f)
|
|
942
|
else:
|
|
943
|
else:
|
|
943
|
lfdirstate.remove(f)
|
|
944
|
lfdirstate.remove(f)
|
|
944
|
lfdirstate.write()
|
|
945
|
lfdirstate.write()
|
|
945
|
lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
|
|
946
|
lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
|
|
946
|
unlink=True)
|
|
947
|
unlink=True)
|
|
947
|
finally:
|
|
948
|
finally:
|
|
948
|
wlock.release()
|
|
949
|
wlock.release()
|
|
949
|
|
|
950
|
|
|
950
|
return result
|
|
951
|
return result
|
|
951
|
|
|
952
|
|
|
952
|
def getoutgoinglfiles(ui, repo, dest=None, **opts):
|
|
953
|
def getoutgoinglfiles(ui, repo, dest=None, **opts):
|
|
953
|
dest = ui.expandpath(dest or 'default-push', dest or 'default')
|
|
954
|
dest = ui.expandpath(dest or 'default-push', dest or 'default')
|
|
954
|
dest, branches = hg.parseurl(dest, opts.get('branch'))
|
|
955
|
dest, branches = hg.parseurl(dest, opts.get('branch'))
|
|
955
|
revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
|
|
956
|
revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
|
|
956
|
if revs:
|
|
957
|
if revs:
|
|
957
|
revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
|
|
958
|
revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
|
|
958
|
|
|
959
|
|
|
959
|
try:
|
|
960
|
try:
|
|
960
|
remote = hg.peer(repo, opts, dest)
|
|
961
|
remote = hg.peer(repo, opts, dest)
|
|
961
|
except error.RepoError:
|
|
962
|
except error.RepoError:
|
|
962
|
return None
|
|
963
|
return None
|
|
963
|
o = lfutil.findoutgoing(repo, remote, False)
|
|
964
|
o = lfutil.findoutgoing(repo, remote, False)
|
|
964
|
if not o:
|
|
965
|
if not o:
|
|
965
|
return None
|
|
966
|
return None
|
|
966
|
o = repo.changelog.nodesbetween(o, revs)[0]
|
|
967
|
o = repo.changelog.nodesbetween(o, revs)[0]
|
|
967
|
if opts.get('newest_first'):
|
|
968
|
if opts.get('newest_first'):
|
|
968
|
o.reverse()
|
|
969
|
o.reverse()
|
|
969
|
|
|
970
|
|
|
970
|
toupload = set()
|
|
971
|
toupload = set()
|
|
971
|
for n in o:
|
|
972
|
for n in o:
|
|
972
|
parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
|
|
973
|
parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
|
|
973
|
ctx = repo[n]
|
|
974
|
ctx = repo[n]
|
|
974
|
files = set(ctx.files())
|
|
975
|
files = set(ctx.files())
|
|
975
|
if len(parents) == 2:
|
|
976
|
if len(parents) == 2:
|
|
976
|
mc = ctx.manifest()
|
|
977
|
mc = ctx.manifest()
|
|
977
|
mp1 = ctx.parents()[0].manifest()
|
|
978
|
mp1 = ctx.parents()[0].manifest()
|
|
978
|
mp2 = ctx.parents()[1].manifest()
|
|
979
|
mp2 = ctx.parents()[1].manifest()
|
|
979
|
for f in mp1:
|
|
980
|
for f in mp1:
|
|
980
|
if f not in mc:
|
|
981
|
if f not in mc:
|
|
981
|
files.add(f)
|
|
982
|
files.add(f)
|
|
982
|
for f in mp2:
|
|
983
|
for f in mp2:
|
|
983
|
if f not in mc:
|
|
984
|
if f not in mc:
|
|
984
|
files.add(f)
|
|
985
|
files.add(f)
|
|
985
|
for f in mc:
|
|
986
|
for f in mc:
|
|
986
|
if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
|
|
987
|
if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
|
|
987
|
files.add(f)
|
|
988
|
files.add(f)
|
|
988
|
toupload = toupload.union(
|
|
989
|
toupload = toupload.union(
|
|
989
|
set([f for f in files if lfutil.isstandin(f) and f in ctx]))
|
|
990
|
set([f for f in files if lfutil.isstandin(f) and f in ctx]))
|
|
990
|
return toupload
|
|
991
|
return toupload
|
|
991
|
|
|
992
|
|
|
992
|
def overrideoutgoing(orig, ui, repo, dest=None, **opts):
|
|
993
|
def overrideoutgoing(orig, ui, repo, dest=None, **opts):
|
|
993
|
result = orig(ui, repo, dest, **opts)
|
|
994
|
result = orig(ui, repo, dest, **opts)
|
|
994
|
|
|
995
|
|
|
995
|
if opts.pop('large', None):
|
|
996
|
if opts.pop('large', None):
|
|
996
|
toupload = getoutgoinglfiles(ui, repo, dest, **opts)
|
|
997
|
toupload = getoutgoinglfiles(ui, repo, dest, **opts)
|
|
997
|
if toupload is None:
|
|
998
|
if toupload is None:
|
|
998
|
ui.status(_('largefiles: No remote repo\n'))
|
|
999
|
ui.status(_('largefiles: No remote repo\n'))
|
|
999
|
else:
|
|
1000
|
else:
|
|
1000
|
ui.status(_('largefiles to upload:\n'))
|
|
1001
|
ui.status(_('largefiles to upload:\n'))
|
|
1001
|
for file in toupload:
|
|
1002
|
for file in toupload:
|
|
1002
|
ui.status(lfutil.splitstandin(file) + '\n')
|
|
1003
|
ui.status(lfutil.splitstandin(file) + '\n')
|
|
1003
|
ui.status('\n')
|
|
1004
|
ui.status('\n')
|
|
1004
|
|
|
1005
|
|
|
1005
|
return result
|
|
1006
|
return result
|
|
1006
|
|
|
1007
|
|
|
1007
|
def overridesummary(orig, ui, repo, *pats, **opts):
|
|
1008
|
def overridesummary(orig, ui, repo, *pats, **opts):
|
|
1008
|
try:
|
|
1009
|
try:
|
|
1009
|
repo.lfstatus = True
|
|
1010
|
repo.lfstatus = True
|
|
1010
|
orig(ui, repo, *pats, **opts)
|
|
1011
|
orig(ui, repo, *pats, **opts)
|
|
1011
|
finally:
|
|
1012
|
finally:
|
|
1012
|
repo.lfstatus = False
|
|
1013
|
repo.lfstatus = False
|
|
1013
|
|
|
1014
|
|
|
1014
|
if opts.pop('large', None):
|
|
1015
|
if opts.pop('large', None):
|
|
1015
|
toupload = getoutgoinglfiles(ui, repo, None, **opts)
|
|
1016
|
toupload = getoutgoinglfiles(ui, repo, None, **opts)
|
|
1016
|
if toupload is None:
|
|
1017
|
if toupload is None:
|
|
1017
|
ui.status(_('largefiles: No remote repo\n'))
|
|
1018
|
ui.status(_('largefiles: No remote repo\n'))
|
|
1018
|
else:
|
|
1019
|
else:
|
|
1019
|
ui.status(_('largefiles: %d to upload\n') % len(toupload))
|
|
1020
|
ui.status(_('largefiles: %d to upload\n') % len(toupload))
|
|
1020
|
|
|
1021
|
|
|
1021
|
def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
|
|
1022
|
def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
|
|
1022
|
similarity=None):
|
|
1023
|
similarity=None):
|
|
1023
|
if not lfutil.islfilesrepo(repo):
|
|
1024
|
if not lfutil.islfilesrepo(repo):
|
|
1024
|
return orig(repo, pats, opts, dry_run, similarity)
|
|
1025
|
return orig(repo, pats, opts, dry_run, similarity)
|
|
1025
|
# Get the list of missing largefiles so we can remove them
|
|
1026
|
# Get the list of missing largefiles so we can remove them
|
|
1026
|
lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
|
|
1027
|
lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
|
|
1027
|
s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
|
|
1028
|
s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
|
|
1028
|
False, False)
|
|
1029
|
False, False)
|
|
1029
|
(unsure, modified, added, removed, missing, unknown, ignored, clean) = s
|
|
1030
|
(unsure, modified, added, removed, missing, unknown, ignored, clean) = s
|
|
1030
|
|
|
1031
|
|
|
1031
|
# Call into the normal remove code, but the removing of the standin, we want
|
|
1032
|
# Call into the normal remove code, but the removing of the standin, we want
|
|
1032
|
# to have handled by original addremove. Monkey patching here makes sure
|
|
1033
|
# to have handled by original addremove. Monkey patching here makes sure
|
|
1033
|
# we don't remove the standin in the largefiles code, preventing a very
|
|
1034
|
# we don't remove the standin in the largefiles code, preventing a very
|
|
1034
|
# confused state later.
|
|
1035
|
# confused state later.
|
|
1035
|
if missing:
|
|
1036
|
if missing:
|
|
1036
|
m = [repo.wjoin(f) for f in missing]
|
|
1037
|
m = [repo.wjoin(f) for f in missing]
|
|
1037
|
repo._isaddremove = True
|
|
1038
|
repo._isaddremove = True
|
|
1038
|
removelargefiles(repo.ui, repo, *m, **opts)
|
|
1039
|
removelargefiles(repo.ui, repo, *m, **opts)
|
|
1039
|
repo._isaddremove = False
|
|
1040
|
repo._isaddremove = False
|
|
1040
|
# Call into the normal add code, and any files that *should* be added as
|
|
1041
|
# Call into the normal add code, and any files that *should* be added as
|
|
1041
|
# largefiles will be
|
|
1042
|
# largefiles will be
|
|
1042
|
addlargefiles(repo.ui, repo, *pats, **opts)
|
|
1043
|
addlargefiles(repo.ui, repo, *pats, **opts)
|
|
1043
|
# Now that we've handled largefiles, hand off to the original addremove
|
|
1044
|
# Now that we've handled largefiles, hand off to the original addremove
|
|
1044
|
# function to take care of the rest. Make sure it doesn't do anything with
|
|
1045
|
# function to take care of the rest. Make sure it doesn't do anything with
|
|
1045
|
# largefiles by installing a matcher that will ignore them.
|
|
1046
|
# largefiles by installing a matcher that will ignore them.
|
|
1046
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
1047
|
installnormalfilesmatchfn(repo[None].manifest())
|
|
1047
|
result = orig(repo, pats, opts, dry_run, similarity)
|
|
1048
|
result = orig(repo, pats, opts, dry_run, similarity)
|
|
1048
|
restorematchfn()
|
|
1049
|
restorematchfn()
|
|
1049
|
return result
|
|
1050
|
return result
|
|
1050
|
|
|
1051
|
|
|
1051
|
# Calling purge with --all will cause the largefiles to be deleted.
|
|
1052
|
# Calling purge with --all will cause the largefiles to be deleted.
|
|
1052
|
# Override repo.status to prevent this from happening.
|
|
1053
|
# Override repo.status to prevent this from happening.
|
|
1053
|
def overridepurge(orig, ui, repo, *dirs, **opts):
|
|
1054
|
def overridepurge(orig, ui, repo, *dirs, **opts):
|
|
1054
|
oldstatus = repo.status
|
|
1055
|
oldstatus = repo.status
|
|
1055
|
def overridestatus(node1='.', node2=None, match=None, ignored=False,
|
|
1056
|
def overridestatus(node1='.', node2=None, match=None, ignored=False,
|
|
1056
|
clean=False, unknown=False, listsubrepos=False):
|
|
1057
|
clean=False, unknown=False, listsubrepos=False):
|
|
1057
|
r = oldstatus(node1, node2, match, ignored, clean, unknown,
|
|
1058
|
r = oldstatus(node1, node2, match, ignored, clean, unknown,
|
|
1058
|
listsubrepos)
|
|
1059
|
listsubrepos)
|
|
1059
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
1060
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
1060
|
modified, added, removed, deleted, unknown, ignored, clean = r
|
|
1061
|
modified, added, removed, deleted, unknown, ignored, clean = r
|
|
1061
|
unknown = [f for f in unknown if lfdirstate[f] == '?']
|
|
1062
|
unknown = [f for f in unknown if lfdirstate[f] == '?']
|
|
1062
|
ignored = [f for f in ignored if lfdirstate[f] == '?']
|
|
1063
|
ignored = [f for f in ignored if lfdirstate[f] == '?']
|
|
1063
|
return modified, added, removed, deleted, unknown, ignored, clean
|
|
1064
|
return modified, added, removed, deleted, unknown, ignored, clean
|
|
1064
|
repo.status = overridestatus
|
|
1065
|
repo.status = overridestatus
|
|
1065
|
orig(ui, repo, *dirs, **opts)
|
|
1066
|
orig(ui, repo, *dirs, **opts)
|
|
1066
|
repo.status = oldstatus
|
|
1067
|
repo.status = oldstatus
|
|
1067
|
|
|
1068
|
|
|
1068
|
def overriderollback(orig, ui, repo, **opts):
|
|
1069
|
def overriderollback(orig, ui, repo, **opts):
|
|
1069
|
result = orig(ui, repo, **opts)
|
|
1070
|
result = orig(ui, repo, **opts)
|
|
1070
|
merge.update(repo, node=None, branchmerge=False, force=True,
|
|
1071
|
merge.update(repo, node=None, branchmerge=False, force=True,
|
|
1071
|
partial=lfutil.isstandin)
|
|
1072
|
partial=lfutil.isstandin)
|
|
1072
|
wlock = repo.wlock()
|
|
1073
|
wlock = repo.wlock()
|
|
1073
|
try:
|
|
1074
|
try:
|
|
1074
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
1075
|
lfdirstate = lfutil.openlfdirstate(ui, repo)
|
|
1075
|
lfiles = lfutil.listlfiles(repo)
|
|
1076
|
lfiles = lfutil.listlfiles(repo)
|
|
1076
|
oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
|
|
1077
|
oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
|
|
1077
|
for file in lfiles:
|
|
1078
|
for file in lfiles:
|
|
1078
|
if file in oldlfiles:
|
|
1079
|
if file in oldlfiles:
|
|
1079
|
lfdirstate.normallookup(file)
|
|
1080
|
lfdirstate.normallookup(file)
|
|
1080
|
else:
|
|
1081
|
else:
|
|
1081
|
lfdirstate.add(file)
|
|
1082
|
lfdirstate.add(file)
|
|
1082
|
lfdirstate.write()
|
|
1083
|
lfdirstate.write()
|
|
1083
|
finally:
|
|
1084
|
finally:
|
|
1084
|
wlock.release()
|
|
1085
|
wlock.release()
|
|
1085
|
return result
|
|
1086
|
return result
|
|
1086
|
|
|
1087
|
|
|
1087
|
def overridetransplant(orig, ui, repo, *revs, **opts):
|
|
1088
|
def overridetransplant(orig, ui, repo, *revs, **opts):
|
|
1088
|
try:
|
|
1089
|
try:
|
|
1089
|
oldstandins = lfutil.getstandinsstate(repo)
|
|
1090
|
oldstandins = lfutil.getstandinsstate(repo)
|
|
1090
|
repo._istransplanting = True
|
|
1091
|
repo._istransplanting = True
|
|
1091
|
result = orig(ui, repo, *revs, **opts)
|
|
1092
|
result = orig(ui, repo, *revs, **opts)
|
|
1092
|
newstandins = lfutil.getstandinsstate(repo)
|
|
1093
|
newstandins = lfutil.getstandinsstate(repo)
|
|
1093
|
filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
|
|
1094
|
filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
|
|
1094
|
lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
|
|
1095
|
lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
|
|
1095
|
printmessage=True)
|
|
1096
|
printmessage=True)
|
|
1096
|
finally:
|
|
1097
|
finally:
|
|
1097
|
repo._istransplanting = False
|
|
1098
|
repo._istransplanting = False
|
|
1098
|
return result
|
|
1099
|
return result
|
|
1099
|
|
|
1100
|
|
|
1100
|
def overridecat(orig, ui, repo, file1, *pats, **opts):
|
|
1101
|
def overridecat(orig, ui, repo, file1, *pats, **opts):
|
|
1101
|
ctx = scmutil.revsingle(repo, opts.get('rev'))
|
|
1102
|
ctx = scmutil.revsingle(repo, opts.get('rev'))
|
|
1102
|
if not lfutil.standin(file1) in ctx:
|
|
1103
|
if not lfutil.standin(file1) in ctx:
|
|
1103
|
result = orig(ui, repo, file1, *pats, **opts)
|
|
1104
|
result = orig(ui, repo, file1, *pats, **opts)
|
|
1104
|
return result
|
|
1105
|
return result
|
|
1105
|
return lfcommands.catlfile(repo, file1, ctx.rev(), opts.get('output'))
|
|
1106
|
return lfcommands.catlfile(repo, file1, ctx.rev(), opts.get('output'))
|