##// END OF EJS Templates
largefiles: drop --cache-largefiles again...
Mads Kiilerich -
r18980:9717a326 default
parent child Browse files
Show More
@@ -1,123 +1,121 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 '''track large binary files
9 '''track large binary files
10
10
11 Large binary files tend to be not very compressible, not very
11 Large binary files tend to be not very compressible, not very
12 diffable, and not at all mergeable. Such files are not handled
12 diffable, and not at all mergeable. Such files are not handled
13 efficiently by Mercurial's storage format (revlog), which is based on
13 efficiently by Mercurial's storage format (revlog), which is based on
14 compressed binary deltas; storing large binary files as regular
14 compressed binary deltas; storing large binary files as regular
15 Mercurial files wastes bandwidth and disk space and increases
15 Mercurial files wastes bandwidth and disk space and increases
16 Mercurial's memory usage. The largefiles extension addresses these
16 Mercurial's memory usage. The largefiles extension addresses these
17 problems by adding a centralized client-server layer on top of
17 problems by adding a centralized client-server layer on top of
18 Mercurial: largefiles live in a *central store* out on the network
18 Mercurial: largefiles live in a *central store* out on the network
19 somewhere, and you only fetch the revisions that you need when you
19 somewhere, and you only fetch the revisions that you need when you
20 need them.
20 need them.
21
21
22 largefiles works by maintaining a "standin file" in .hglf/ for each
22 largefiles works by maintaining a "standin file" in .hglf/ for each
23 largefile. The standins are small (41 bytes: an SHA-1 hash plus
23 largefile. The standins are small (41 bytes: an SHA-1 hash plus
24 newline) and are tracked by Mercurial. Largefile revisions are
24 newline) and are tracked by Mercurial. Largefile revisions are
25 identified by the SHA-1 hash of their contents, which is written to
25 identified by the SHA-1 hash of their contents, which is written to
26 the standin. largefiles uses that revision ID to get/put largefile
26 the standin. largefiles uses that revision ID to get/put largefile
27 revisions from/to the central store. This saves both disk space and
27 revisions from/to the central store. This saves both disk space and
28 bandwidth, since you don't need to retrieve all historical revisions
28 bandwidth, since you don't need to retrieve all historical revisions
29 of large files when you clone or pull.
29 of large files when you clone or pull.
30
30
31 To start a new repository or add new large binary files, just add
31 To start a new repository or add new large binary files, just add
32 --large to your :hg:`add` command. For example::
32 --large to your :hg:`add` command. For example::
33
33
34 $ dd if=/dev/urandom of=randomdata count=2000
34 $ dd if=/dev/urandom of=randomdata count=2000
35 $ hg add --large randomdata
35 $ hg add --large randomdata
36 $ hg commit -m 'add randomdata as a largefile'
36 $ hg commit -m 'add randomdata as a largefile'
37
37
38 When you push a changeset that adds/modifies largefiles to a remote
38 When you push a changeset that adds/modifies largefiles to a remote
39 repository, its largefile revisions will be uploaded along with it.
39 repository, its largefile revisions will be uploaded along with it.
40 Note that the remote Mercurial must also have the largefiles extension
40 Note that the remote Mercurial must also have the largefiles extension
41 enabled for this to work.
41 enabled for this to work.
42
42
43 When you pull a changeset that affects largefiles from a remote
43 When you pull a changeset that affects largefiles from a remote
44 repository, the largefiles for the changeset will by default not be
44 repository, the largefiles for the changeset will by default not be
45 pulled down. However, when you update to such a revision, any
45 pulled down. However, when you update to such a revision, any
46 largefiles needed by that revision are downloaded and cached (if
46 largefiles needed by that revision are downloaded and cached (if
47 they have never been downloaded before). One way to pull largefiles
47 they have never been downloaded before). One way to pull largefiles
48 when pulling is thus to use --update, which will update your working
48 when pulling is thus to use --update, which will update your working
49 copy to the latest pulled revision (and thereby downloading any new
49 copy to the latest pulled revision (and thereby downloading any new
50 largefiles).
50 largefiles).
51
51
52 If you want to pull largefiles you don't need for update yet, then
52 If you want to pull largefiles you don't need for update yet, then
53 you can use pull with the `--lfrev` option or the :hg:`lfpull` command.
53 you can use pull with the `--lfrev` option or the :hg:`lfpull` command.
54
54
55 If you know you are pulling from a non-default location and want do
55 If you know you are pulling from a non-default location and want do
56 download all the largefiles that corresponds to the new changesets at
56 download all the largefiles that corresponds to the new changesets at
57 the same time, then you can pull with `--lfrev "pulled()"`.
57 the same time, then you can pull with `--lfrev "pulled()"`.
58
58
59 If you just want to ensure that you will have the largefiles needed to
59 If you just want to ensure that you will have the largefiles needed to
60 merge or rebase with new heads that you are pulling, then you can pull
60 merge or rebase with new heads that you are pulling, then you can pull
61 with `--lfrev "head(pulled())"` flag to pre-emptively download any largefiles
61 with `--lfrev "head(pulled())"` flag to pre-emptively download any largefiles
62 that are new in the heads you are pulling. You can also pull with the
63 `--cache-largefiles` flag to pre-emptively download any largefiles
64 that are new in the heads you are pulling.
62 that are new in the heads you are pulling.
65
63
66 Keep in mind that network access may now be required to update to
64 Keep in mind that network access may now be required to update to
67 changesets that you have not previously updated to. The nature of the
65 changesets that you have not previously updated to. The nature of the
68 largefiles extension means that updating is no longer guaranteed to
66 largefiles extension means that updating is no longer guaranteed to
69 be a local-only operation.
67 be a local-only operation.
70
68
71 If you already have large files tracked by Mercurial without the
69 If you already have large files tracked by Mercurial without the
72 largefiles extension, you will need to convert your repository in
70 largefiles extension, you will need to convert your repository in
73 order to benefit from largefiles. This is done with the
71 order to benefit from largefiles. This is done with the
74 :hg:`lfconvert` command::
72 :hg:`lfconvert` command::
75
73
76 $ hg lfconvert --size 10 oldrepo newrepo
74 $ hg lfconvert --size 10 oldrepo newrepo
77
75
78 In repositories that already have largefiles in them, any new file
76 In repositories that already have largefiles in them, any new file
79 over 10MB will automatically be added as a largefile. To change this
77 over 10MB will automatically be added as a largefile. To change this
80 threshold, set ``largefiles.minsize`` in your Mercurial config file
78 threshold, set ``largefiles.minsize`` in your Mercurial config file
81 to the minimum size in megabytes to track as a largefile, or use the
79 to the minimum size in megabytes to track as a largefile, or use the
82 --lfsize option to the add command (also in megabytes)::
80 --lfsize option to the add command (also in megabytes)::
83
81
84 [largefiles]
82 [largefiles]
85 minsize = 2
83 minsize = 2
86
84
87 $ hg add --lfsize 2
85 $ hg add --lfsize 2
88
86
89 The ``largefiles.patterns`` config option allows you to specify a list
87 The ``largefiles.patterns`` config option allows you to specify a list
90 of filename patterns (see :hg:`help patterns`) that should always be
88 of filename patterns (see :hg:`help patterns`) that should always be
91 tracked as largefiles::
89 tracked as largefiles::
92
90
93 [largefiles]
91 [largefiles]
94 patterns =
92 patterns =
95 *.jpg
93 *.jpg
96 re:.*\.(png|bmp)$
94 re:.*\.(png|bmp)$
97 library.zip
95 library.zip
98 content/audio/*
96 content/audio/*
99
97
100 Files that match one of these patterns will be added as largefiles
98 Files that match one of these patterns will be added as largefiles
101 regardless of their size.
99 regardless of their size.
102
100
103 The ``largefiles.minsize`` and ``largefiles.patterns`` config options
101 The ``largefiles.minsize`` and ``largefiles.patterns`` config options
104 will be ignored for any repositories not already containing a
102 will be ignored for any repositories not already containing a
105 largefile. To add the first largefile to a repository, you must
103 largefile. To add the first largefile to a repository, you must
106 explicitly do so with the --large flag passed to the :hg:`add`
104 explicitly do so with the --large flag passed to the :hg:`add`
107 command.
105 command.
108 '''
106 '''
109
107
110 from mercurial import commands
108 from mercurial import commands
111
109
112 import lfcommands
110 import lfcommands
113 import reposetup
111 import reposetup
114 import uisetup
112 import uisetup
115
113
116 testedwith = 'internal'
114 testedwith = 'internal'
117
115
118 reposetup = reposetup.reposetup
116 reposetup = reposetup.reposetup
119 uisetup = uisetup.uisetup
117 uisetup = uisetup.uisetup
120
118
121 commands.norepo += " lfconvert"
119 commands.norepo += " lfconvert"
122
120
123 cmdtable = lfcommands.cmdtable
121 cmdtable = lfcommands.cmdtable
@@ -1,427 +1,419 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 '''largefiles utility code: must not import other modules in this package.'''
9 '''largefiles utility code: must not import other modules in this package.'''
10
10
11 import os
11 import os
12 import errno
12 import errno
13 import platform
13 import platform
14 import shutil
14 import shutil
15 import stat
15 import stat
16
16
17 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
17 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
18 from mercurial.i18n import _
18 from mercurial.i18n import _
19
19
20 shortname = '.hglf'
20 shortname = '.hglf'
21 shortnameslash = shortname + '/'
21 shortnameslash = shortname + '/'
22 longname = 'largefiles'
22 longname = 'largefiles'
23
23
24
24
25 # -- Private worker functions ------------------------------------------
25 # -- Private worker functions ------------------------------------------
26
26
27 def getminsize(ui, assumelfiles, opt, default=10):
27 def getminsize(ui, assumelfiles, opt, default=10):
28 lfsize = opt
28 lfsize = opt
29 if not lfsize and assumelfiles:
29 if not lfsize and assumelfiles:
30 lfsize = ui.config(longname, 'minsize', default=default)
30 lfsize = ui.config(longname, 'minsize', default=default)
31 if lfsize:
31 if lfsize:
32 try:
32 try:
33 lfsize = float(lfsize)
33 lfsize = float(lfsize)
34 except ValueError:
34 except ValueError:
35 raise util.Abort(_('largefiles: size must be number (not %s)\n')
35 raise util.Abort(_('largefiles: size must be number (not %s)\n')
36 % lfsize)
36 % lfsize)
37 if lfsize is None:
37 if lfsize is None:
38 raise util.Abort(_('minimum size for largefiles must be specified'))
38 raise util.Abort(_('minimum size for largefiles must be specified'))
39 return lfsize
39 return lfsize
40
40
41 def link(src, dest):
41 def link(src, dest):
42 try:
42 try:
43 util.oslink(src, dest)
43 util.oslink(src, dest)
44 except OSError:
44 except OSError:
45 # if hardlinks fail, fallback on atomic copy
45 # if hardlinks fail, fallback on atomic copy
46 dst = util.atomictempfile(dest)
46 dst = util.atomictempfile(dest)
47 for chunk in util.filechunkiter(open(src, 'rb')):
47 for chunk in util.filechunkiter(open(src, 'rb')):
48 dst.write(chunk)
48 dst.write(chunk)
49 dst.close()
49 dst.close()
50 os.chmod(dest, os.stat(src).st_mode)
50 os.chmod(dest, os.stat(src).st_mode)
51
51
52 def usercachepath(ui, hash):
52 def usercachepath(ui, hash):
53 path = ui.configpath(longname, 'usercache', None)
53 path = ui.configpath(longname, 'usercache', None)
54 if path:
54 if path:
55 path = os.path.join(path, hash)
55 path = os.path.join(path, hash)
56 else:
56 else:
57 if os.name == 'nt':
57 if os.name == 'nt':
58 appdata = os.getenv('LOCALAPPDATA', os.getenv('APPDATA'))
58 appdata = os.getenv('LOCALAPPDATA', os.getenv('APPDATA'))
59 if appdata:
59 if appdata:
60 path = os.path.join(appdata, longname, hash)
60 path = os.path.join(appdata, longname, hash)
61 elif platform.system() == 'Darwin':
61 elif platform.system() == 'Darwin':
62 home = os.getenv('HOME')
62 home = os.getenv('HOME')
63 if home:
63 if home:
64 path = os.path.join(home, 'Library', 'Caches',
64 path = os.path.join(home, 'Library', 'Caches',
65 longname, hash)
65 longname, hash)
66 elif os.name == 'posix':
66 elif os.name == 'posix':
67 path = os.getenv('XDG_CACHE_HOME')
67 path = os.getenv('XDG_CACHE_HOME')
68 if path:
68 if path:
69 path = os.path.join(path, longname, hash)
69 path = os.path.join(path, longname, hash)
70 else:
70 else:
71 home = os.getenv('HOME')
71 home = os.getenv('HOME')
72 if home:
72 if home:
73 path = os.path.join(home, '.cache', longname, hash)
73 path = os.path.join(home, '.cache', longname, hash)
74 else:
74 else:
75 raise util.Abort(_('unknown operating system: %s\n') % os.name)
75 raise util.Abort(_('unknown operating system: %s\n') % os.name)
76 return path
76 return path
77
77
78 def inusercache(ui, hash):
78 def inusercache(ui, hash):
79 path = usercachepath(ui, hash)
79 path = usercachepath(ui, hash)
80 return path and os.path.exists(path)
80 return path and os.path.exists(path)
81
81
82 def findfile(repo, hash):
82 def findfile(repo, hash):
83 if instore(repo, hash):
83 if instore(repo, hash):
84 repo.ui.note(_('found %s in store\n') % hash)
84 repo.ui.note(_('found %s in store\n') % hash)
85 return storepath(repo, hash)
85 return storepath(repo, hash)
86 elif inusercache(repo.ui, hash):
86 elif inusercache(repo.ui, hash):
87 repo.ui.note(_('found %s in system cache\n') % hash)
87 repo.ui.note(_('found %s in system cache\n') % hash)
88 path = storepath(repo, hash)
88 path = storepath(repo, hash)
89 util.makedirs(os.path.dirname(path))
89 util.makedirs(os.path.dirname(path))
90 link(usercachepath(repo.ui, hash), path)
90 link(usercachepath(repo.ui, hash), path)
91 return path
91 return path
92 return None
92 return None
93
93
94 class largefilesdirstate(dirstate.dirstate):
94 class largefilesdirstate(dirstate.dirstate):
95 def __getitem__(self, key):
95 def __getitem__(self, key):
96 return super(largefilesdirstate, self).__getitem__(unixpath(key))
96 return super(largefilesdirstate, self).__getitem__(unixpath(key))
97 def normal(self, f):
97 def normal(self, f):
98 return super(largefilesdirstate, self).normal(unixpath(f))
98 return super(largefilesdirstate, self).normal(unixpath(f))
99 def remove(self, f):
99 def remove(self, f):
100 return super(largefilesdirstate, self).remove(unixpath(f))
100 return super(largefilesdirstate, self).remove(unixpath(f))
101 def add(self, f):
101 def add(self, f):
102 return super(largefilesdirstate, self).add(unixpath(f))
102 return super(largefilesdirstate, self).add(unixpath(f))
103 def drop(self, f):
103 def drop(self, f):
104 return super(largefilesdirstate, self).drop(unixpath(f))
104 return super(largefilesdirstate, self).drop(unixpath(f))
105 def forget(self, f):
105 def forget(self, f):
106 return super(largefilesdirstate, self).forget(unixpath(f))
106 return super(largefilesdirstate, self).forget(unixpath(f))
107 def normallookup(self, f):
107 def normallookup(self, f):
108 return super(largefilesdirstate, self).normallookup(unixpath(f))
108 return super(largefilesdirstate, self).normallookup(unixpath(f))
109 def _ignore(self):
109 def _ignore(self):
110 return False
110 return False
111
111
112 def openlfdirstate(ui, repo, create=True):
112 def openlfdirstate(ui, repo, create=True):
113 '''
113 '''
114 Return a dirstate object that tracks largefiles: i.e. its root is
114 Return a dirstate object that tracks largefiles: i.e. its root is
115 the repo root, but it is saved in .hg/largefiles/dirstate.
115 the repo root, but it is saved in .hg/largefiles/dirstate.
116 '''
116 '''
117 lfstoredir = repo.join(longname)
117 lfstoredir = repo.join(longname)
118 opener = scmutil.opener(lfstoredir)
118 opener = scmutil.opener(lfstoredir)
119 lfdirstate = largefilesdirstate(opener, ui, repo.root,
119 lfdirstate = largefilesdirstate(opener, ui, repo.root,
120 repo.dirstate._validate)
120 repo.dirstate._validate)
121
121
122 # If the largefiles dirstate does not exist, populate and create
122 # If the largefiles dirstate does not exist, populate and create
123 # it. This ensures that we create it on the first meaningful
123 # it. This ensures that we create it on the first meaningful
124 # largefiles operation in a new clone.
124 # largefiles operation in a new clone.
125 if create and not os.path.exists(os.path.join(lfstoredir, 'dirstate')):
125 if create and not os.path.exists(os.path.join(lfstoredir, 'dirstate')):
126 util.makedirs(lfstoredir)
126 util.makedirs(lfstoredir)
127 matcher = getstandinmatcher(repo)
127 matcher = getstandinmatcher(repo)
128 for standin in repo.dirstate.walk(matcher, [], False, False):
128 for standin in repo.dirstate.walk(matcher, [], False, False):
129 lfile = splitstandin(standin)
129 lfile = splitstandin(standin)
130 hash = readstandin(repo, lfile)
130 hash = readstandin(repo, lfile)
131 lfdirstate.normallookup(lfile)
131 lfdirstate.normallookup(lfile)
132 try:
132 try:
133 if hash == hashfile(repo.wjoin(lfile)):
133 if hash == hashfile(repo.wjoin(lfile)):
134 lfdirstate.normal(lfile)
134 lfdirstate.normal(lfile)
135 except OSError, err:
135 except OSError, err:
136 if err.errno != errno.ENOENT:
136 if err.errno != errno.ENOENT:
137 raise
137 raise
138 return lfdirstate
138 return lfdirstate
139
139
140 def lfdirstatestatus(lfdirstate, repo, rev):
140 def lfdirstatestatus(lfdirstate, repo, rev):
141 match = match_.always(repo.root, repo.getcwd())
141 match = match_.always(repo.root, repo.getcwd())
142 s = lfdirstate.status(match, [], False, False, False)
142 s = lfdirstate.status(match, [], False, False, False)
143 unsure, modified, added, removed, missing, unknown, ignored, clean = s
143 unsure, modified, added, removed, missing, unknown, ignored, clean = s
144 for lfile in unsure:
144 for lfile in unsure:
145 try:
145 try:
146 fctx = repo[rev][standin(lfile)]
146 fctx = repo[rev][standin(lfile)]
147 except LookupError:
147 except LookupError:
148 fctx = None
148 fctx = None
149 if not fctx or fctx.data().strip() != hashfile(repo.wjoin(lfile)):
149 if not fctx or fctx.data().strip() != hashfile(repo.wjoin(lfile)):
150 modified.append(lfile)
150 modified.append(lfile)
151 else:
151 else:
152 clean.append(lfile)
152 clean.append(lfile)
153 lfdirstate.normal(lfile)
153 lfdirstate.normal(lfile)
154 return (modified, added, removed, missing, unknown, ignored, clean)
154 return (modified, added, removed, missing, unknown, ignored, clean)
155
155
156 def listlfiles(repo, rev=None, matcher=None):
156 def listlfiles(repo, rev=None, matcher=None):
157 '''return a list of largefiles in the working copy or the
157 '''return a list of largefiles in the working copy or the
158 specified changeset'''
158 specified changeset'''
159
159
160 if matcher is None:
160 if matcher is None:
161 matcher = getstandinmatcher(repo)
161 matcher = getstandinmatcher(repo)
162
162
163 # ignore unknown files in working directory
163 # ignore unknown files in working directory
164 return [splitstandin(f)
164 return [splitstandin(f)
165 for f in repo[rev].walk(matcher)
165 for f in repo[rev].walk(matcher)
166 if rev is not None or repo.dirstate[f] != '?']
166 if rev is not None or repo.dirstate[f] != '?']
167
167
168 def instore(repo, hash):
168 def instore(repo, hash):
169 return os.path.exists(storepath(repo, hash))
169 return os.path.exists(storepath(repo, hash))
170
170
171 def storepath(repo, hash):
171 def storepath(repo, hash):
172 return repo.join(os.path.join(longname, hash))
172 return repo.join(os.path.join(longname, hash))
173
173
174 def copyfromcache(repo, hash, filename):
174 def copyfromcache(repo, hash, filename):
175 '''Copy the specified largefile from the repo or system cache to
175 '''Copy the specified largefile from the repo or system cache to
176 filename in the repository. Return true on success or false if the
176 filename in the repository. Return true on success or false if the
177 file was not found in either cache (which should not happened:
177 file was not found in either cache (which should not happened:
178 this is meant to be called only after ensuring that the needed
178 this is meant to be called only after ensuring that the needed
179 largefile exists in the cache).'''
179 largefile exists in the cache).'''
180 path = findfile(repo, hash)
180 path = findfile(repo, hash)
181 if path is None:
181 if path is None:
182 return False
182 return False
183 util.makedirs(os.path.dirname(repo.wjoin(filename)))
183 util.makedirs(os.path.dirname(repo.wjoin(filename)))
184 # The write may fail before the file is fully written, but we
184 # The write may fail before the file is fully written, but we
185 # don't use atomic writes in the working copy.
185 # don't use atomic writes in the working copy.
186 shutil.copy(path, repo.wjoin(filename))
186 shutil.copy(path, repo.wjoin(filename))
187 return True
187 return True
188
188
189 def copytostore(repo, rev, file, uploaded=False):
189 def copytostore(repo, rev, file, uploaded=False):
190 hash = readstandin(repo, file, rev)
190 hash = readstandin(repo, file, rev)
191 if instore(repo, hash):
191 if instore(repo, hash):
192 return
192 return
193 copytostoreabsolute(repo, repo.wjoin(file), hash)
193 copytostoreabsolute(repo, repo.wjoin(file), hash)
194
194
195 def copyalltostore(repo, node):
195 def copyalltostore(repo, node):
196 '''Copy all largefiles in a given revision to the store'''
196 '''Copy all largefiles in a given revision to the store'''
197
197
198 ctx = repo[node]
198 ctx = repo[node]
199 for filename in ctx.files():
199 for filename in ctx.files():
200 if isstandin(filename) and filename in ctx.manifest():
200 if isstandin(filename) and filename in ctx.manifest():
201 realfile = splitstandin(filename)
201 realfile = splitstandin(filename)
202 copytostore(repo, ctx.node(), realfile)
202 copytostore(repo, ctx.node(), realfile)
203
203
204
204
205 def copytostoreabsolute(repo, file, hash):
205 def copytostoreabsolute(repo, file, hash):
206 util.makedirs(os.path.dirname(storepath(repo, hash)))
206 util.makedirs(os.path.dirname(storepath(repo, hash)))
207 if inusercache(repo.ui, hash):
207 if inusercache(repo.ui, hash):
208 link(usercachepath(repo.ui, hash), storepath(repo, hash))
208 link(usercachepath(repo.ui, hash), storepath(repo, hash))
209 elif not getattr(repo, "_isconverting", False):
209 elif not getattr(repo, "_isconverting", False):
210 dst = util.atomictempfile(storepath(repo, hash),
210 dst = util.atomictempfile(storepath(repo, hash),
211 createmode=repo.store.createmode)
211 createmode=repo.store.createmode)
212 for chunk in util.filechunkiter(open(file, 'rb')):
212 for chunk in util.filechunkiter(open(file, 'rb')):
213 dst.write(chunk)
213 dst.write(chunk)
214 dst.close()
214 dst.close()
215 linktousercache(repo, hash)
215 linktousercache(repo, hash)
216
216
217 def linktousercache(repo, hash):
217 def linktousercache(repo, hash):
218 path = usercachepath(repo.ui, hash)
218 path = usercachepath(repo.ui, hash)
219 if path:
219 if path:
220 util.makedirs(os.path.dirname(path))
220 util.makedirs(os.path.dirname(path))
221 link(storepath(repo, hash), path)
221 link(storepath(repo, hash), path)
222
222
223 def getstandinmatcher(repo, pats=[], opts={}):
223 def getstandinmatcher(repo, pats=[], opts={}):
224 '''Return a match object that applies pats to the standin directory'''
224 '''Return a match object that applies pats to the standin directory'''
225 standindir = repo.wjoin(shortname)
225 standindir = repo.wjoin(shortname)
226 if pats:
226 if pats:
227 pats = [os.path.join(standindir, pat) for pat in pats]
227 pats = [os.path.join(standindir, pat) for pat in pats]
228 else:
228 else:
229 # no patterns: relative to repo root
229 # no patterns: relative to repo root
230 pats = [standindir]
230 pats = [standindir]
231 # no warnings about missing files or directories
231 # no warnings about missing files or directories
232 match = scmutil.match(repo[None], pats, opts)
232 match = scmutil.match(repo[None], pats, opts)
233 match.bad = lambda f, msg: None
233 match.bad = lambda f, msg: None
234 return match
234 return match
235
235
236 def composestandinmatcher(repo, rmatcher):
236 def composestandinmatcher(repo, rmatcher):
237 '''Return a matcher that accepts standins corresponding to the
237 '''Return a matcher that accepts standins corresponding to the
238 files accepted by rmatcher. Pass the list of files in the matcher
238 files accepted by rmatcher. Pass the list of files in the matcher
239 as the paths specified by the user.'''
239 as the paths specified by the user.'''
240 smatcher = getstandinmatcher(repo, rmatcher.files())
240 smatcher = getstandinmatcher(repo, rmatcher.files())
241 isstandin = smatcher.matchfn
241 isstandin = smatcher.matchfn
242 def composedmatchfn(f):
242 def composedmatchfn(f):
243 return isstandin(f) and rmatcher.matchfn(splitstandin(f))
243 return isstandin(f) and rmatcher.matchfn(splitstandin(f))
244 smatcher.matchfn = composedmatchfn
244 smatcher.matchfn = composedmatchfn
245
245
246 return smatcher
246 return smatcher
247
247
248 def standin(filename):
248 def standin(filename):
249 '''Return the repo-relative path to the standin for the specified big
249 '''Return the repo-relative path to the standin for the specified big
250 file.'''
250 file.'''
251 # Notes:
251 # Notes:
252 # 1) Some callers want an absolute path, but for instance addlargefiles
252 # 1) Some callers want an absolute path, but for instance addlargefiles
253 # needs it repo-relative so it can be passed to repo[None].add(). So
253 # needs it repo-relative so it can be passed to repo[None].add(). So
254 # leave it up to the caller to use repo.wjoin() to get an absolute path.
254 # leave it up to the caller to use repo.wjoin() to get an absolute path.
255 # 2) Join with '/' because that's what dirstate always uses, even on
255 # 2) Join with '/' because that's what dirstate always uses, even on
256 # Windows. Change existing separator to '/' first in case we are
256 # Windows. Change existing separator to '/' first in case we are
257 # passed filenames from an external source (like the command line).
257 # passed filenames from an external source (like the command line).
258 return shortnameslash + util.pconvert(filename)
258 return shortnameslash + util.pconvert(filename)
259
259
260 def isstandin(filename):
260 def isstandin(filename):
261 '''Return true if filename is a big file standin. filename must be
261 '''Return true if filename is a big file standin. filename must be
262 in Mercurial's internal form (slash-separated).'''
262 in Mercurial's internal form (slash-separated).'''
263 return filename.startswith(shortnameslash)
263 return filename.startswith(shortnameslash)
264
264
265 def splitstandin(filename):
265 def splitstandin(filename):
266 # Split on / because that's what dirstate always uses, even on Windows.
266 # Split on / because that's what dirstate always uses, even on Windows.
267 # Change local separator to / first just in case we are passed filenames
267 # Change local separator to / first just in case we are passed filenames
268 # from an external source (like the command line).
268 # from an external source (like the command line).
269 bits = util.pconvert(filename).split('/', 1)
269 bits = util.pconvert(filename).split('/', 1)
270 if len(bits) == 2 and bits[0] == shortname:
270 if len(bits) == 2 and bits[0] == shortname:
271 return bits[1]
271 return bits[1]
272 else:
272 else:
273 return None
273 return None
274
274
275 def updatestandin(repo, standin):
275 def updatestandin(repo, standin):
276 file = repo.wjoin(splitstandin(standin))
276 file = repo.wjoin(splitstandin(standin))
277 if os.path.exists(file):
277 if os.path.exists(file):
278 hash = hashfile(file)
278 hash = hashfile(file)
279 executable = getexecutable(file)
279 executable = getexecutable(file)
280 writestandin(repo, standin, hash, executable)
280 writestandin(repo, standin, hash, executable)
281
281
282 def readstandin(repo, filename, node=None):
282 def readstandin(repo, filename, node=None):
283 '''read hex hash from standin for filename at given node, or working
283 '''read hex hash from standin for filename at given node, or working
284 directory if no node is given'''
284 directory if no node is given'''
285 return repo[node][standin(filename)].data().strip()
285 return repo[node][standin(filename)].data().strip()
286
286
287 def writestandin(repo, standin, hash, executable):
287 def writestandin(repo, standin, hash, executable):
288 '''write hash to <repo.root>/<standin>'''
288 '''write hash to <repo.root>/<standin>'''
289 writehash(hash, repo.wjoin(standin), executable)
289 writehash(hash, repo.wjoin(standin), executable)
290
290
291 def copyandhash(instream, outfile):
291 def copyandhash(instream, outfile):
292 '''Read bytes from instream (iterable) and write them to outfile,
292 '''Read bytes from instream (iterable) and write them to outfile,
293 computing the SHA-1 hash of the data along the way. Close outfile
293 computing the SHA-1 hash of the data along the way. Close outfile
294 when done and return the binary hash.'''
294 when done and return the binary hash.'''
295 hasher = util.sha1('')
295 hasher = util.sha1('')
296 for data in instream:
296 for data in instream:
297 hasher.update(data)
297 hasher.update(data)
298 outfile.write(data)
298 outfile.write(data)
299
299
300 # Blecch: closing a file that somebody else opened is rude and
300 # Blecch: closing a file that somebody else opened is rude and
301 # wrong. But it's so darn convenient and practical! After all,
301 # wrong. But it's so darn convenient and practical! After all,
302 # outfile was opened just to copy and hash.
302 # outfile was opened just to copy and hash.
303 outfile.close()
303 outfile.close()
304
304
305 return hasher.digest()
305 return hasher.digest()
306
306
307 def hashrepofile(repo, file):
307 def hashrepofile(repo, file):
308 return hashfile(repo.wjoin(file))
308 return hashfile(repo.wjoin(file))
309
309
310 def hashfile(file):
310 def hashfile(file):
311 if not os.path.exists(file):
311 if not os.path.exists(file):
312 return ''
312 return ''
313 hasher = util.sha1('')
313 hasher = util.sha1('')
314 fd = open(file, 'rb')
314 fd = open(file, 'rb')
315 for data in blockstream(fd):
315 for data in blockstream(fd):
316 hasher.update(data)
316 hasher.update(data)
317 fd.close()
317 fd.close()
318 return hasher.hexdigest()
318 return hasher.hexdigest()
319
319
320 class limitreader(object):
320 class limitreader(object):
321 def __init__(self, f, limit):
321 def __init__(self, f, limit):
322 self.f = f
322 self.f = f
323 self.limit = limit
323 self.limit = limit
324
324
325 def read(self, length):
325 def read(self, length):
326 if self.limit == 0:
326 if self.limit == 0:
327 return ''
327 return ''
328 length = length > self.limit and self.limit or length
328 length = length > self.limit and self.limit or length
329 self.limit -= length
329 self.limit -= length
330 return self.f.read(length)
330 return self.f.read(length)
331
331
332 def close(self):
332 def close(self):
333 pass
333 pass
334
334
335 def blockstream(infile, blocksize=128 * 1024):
335 def blockstream(infile, blocksize=128 * 1024):
336 """Generator that yields blocks of data from infile and closes infile."""
336 """Generator that yields blocks of data from infile and closes infile."""
337 while True:
337 while True:
338 data = infile.read(blocksize)
338 data = infile.read(blocksize)
339 if not data:
339 if not data:
340 break
340 break
341 yield data
341 yield data
342 # same blecch as copyandhash() above
342 # same blecch as copyandhash() above
343 infile.close()
343 infile.close()
344
344
345 def writehash(hash, filename, executable):
345 def writehash(hash, filename, executable):
346 util.makedirs(os.path.dirname(filename))
346 util.makedirs(os.path.dirname(filename))
347 util.writefile(filename, hash + '\n')
347 util.writefile(filename, hash + '\n')
348 os.chmod(filename, getmode(executable))
348 os.chmod(filename, getmode(executable))
349
349
350 def getexecutable(filename):
350 def getexecutable(filename):
351 mode = os.stat(filename).st_mode
351 mode = os.stat(filename).st_mode
352 return ((mode & stat.S_IXUSR) and
352 return ((mode & stat.S_IXUSR) and
353 (mode & stat.S_IXGRP) and
353 (mode & stat.S_IXGRP) and
354 (mode & stat.S_IXOTH))
354 (mode & stat.S_IXOTH))
355
355
356 def getmode(executable):
356 def getmode(executable):
357 if executable:
357 if executable:
358 return 0755
358 return 0755
359 else:
359 else:
360 return 0644
360 return 0644
361
361
362 def urljoin(first, second, *arg):
362 def urljoin(first, second, *arg):
363 def join(left, right):
363 def join(left, right):
364 if not left.endswith('/'):
364 if not left.endswith('/'):
365 left += '/'
365 left += '/'
366 if right.startswith('/'):
366 if right.startswith('/'):
367 right = right[1:]
367 right = right[1:]
368 return left + right
368 return left + right
369
369
370 url = join(first, second)
370 url = join(first, second)
371 for a in arg:
371 for a in arg:
372 url = join(url, a)
372 url = join(url, a)
373 return url
373 return url
374
374
375 def hexsha1(data):
375 def hexsha1(data):
376 """hexsha1 returns the hex-encoded sha1 sum of the data in the file-like
376 """hexsha1 returns the hex-encoded sha1 sum of the data in the file-like
377 object data"""
377 object data"""
378 h = util.sha1()
378 h = util.sha1()
379 for chunk in util.filechunkiter(data):
379 for chunk in util.filechunkiter(data):
380 h.update(chunk)
380 h.update(chunk)
381 return h.hexdigest()
381 return h.hexdigest()
382
382
383 def httpsendfile(ui, filename):
383 def httpsendfile(ui, filename):
384 return httpconnection.httpsendfile(ui, filename, 'rb')
384 return httpconnection.httpsendfile(ui, filename, 'rb')
385
385
386 def unixpath(path):
386 def unixpath(path):
387 '''Return a version of path normalized for use with the lfdirstate.'''
387 '''Return a version of path normalized for use with the lfdirstate.'''
388 return util.pconvert(os.path.normpath(path))
388 return util.pconvert(os.path.normpath(path))
389
389
390 def islfilesrepo(repo):
390 def islfilesrepo(repo):
391 if ('largefiles' in repo.requirements and
391 if ('largefiles' in repo.requirements and
392 util.any(shortnameslash in f[0] for f in repo.store.datafiles())):
392 util.any(shortnameslash in f[0] for f in repo.store.datafiles())):
393 return True
393 return True
394
394
395 return util.any(openlfdirstate(repo.ui, repo, False))
395 return util.any(openlfdirstate(repo.ui, repo, False))
396
396
397 class storeprotonotcapable(Exception):
397 class storeprotonotcapable(Exception):
398 def __init__(self, storetypes):
398 def __init__(self, storetypes):
399 self.storetypes = storetypes
399 self.storetypes = storetypes
400
400
401 def getcurrentheads(repo):
402 branches = repo.branchmap()
403 heads = []
404 for branch in branches:
405 newheads = repo.branchheads(branch)
406 heads = heads + newheads
407 return heads
408
409 def getstandinsstate(repo):
401 def getstandinsstate(repo):
410 standins = []
402 standins = []
411 matcher = getstandinmatcher(repo)
403 matcher = getstandinmatcher(repo)
412 for standin in repo.dirstate.walk(matcher, [], False, False):
404 for standin in repo.dirstate.walk(matcher, [], False, False):
413 lfile = splitstandin(standin)
405 lfile = splitstandin(standin)
414 try:
406 try:
415 hash = readstandin(repo, lfile)
407 hash = readstandin(repo, lfile)
416 except IOError:
408 except IOError:
417 hash = None
409 hash = None
418 standins.append((lfile, hash))
410 standins.append((lfile, hash))
419 return standins
411 return standins
420
412
421 def getlfilestoupdate(oldstandins, newstandins):
413 def getlfilestoupdate(oldstandins, newstandins):
422 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
414 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
423 filelist = []
415 filelist = []
424 for f in changedstandins:
416 for f in changedstandins:
425 if f[0] not in filelist:
417 if f[0] not in filelist:
426 filelist.append(f[0])
418 filelist.append(f[0])
427 return filelist
419 return filelist
@@ -1,1233 +1,1217 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, discovery
15 node, archival, error, merge, discovery
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 import basestore
22 import basestore
23
23
24 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24 # -- Utility functions: commonly/repeatedly needed functionality ---------------
25
25
26 def installnormalfilesmatchfn(manifest):
26 def installnormalfilesmatchfn(manifest):
27 '''overrides scmutil.match so that the matcher it returns will ignore all
27 '''overrides scmutil.match so that the matcher it returns will ignore all
28 largefiles'''
28 largefiles'''
29 oldmatch = None # for the closure
29 oldmatch = None # for the closure
30 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 def overridematch(ctx, pats=[], opts={}, globbed=False,
31 default='relpath'):
31 default='relpath'):
32 match = oldmatch(ctx, pats, opts, globbed, default)
32 match = oldmatch(ctx, pats, opts, globbed, default)
33 m = copy.copy(match)
33 m = copy.copy(match)
34 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
35 manifest)
35 manifest)
36 m._files = filter(notlfile, m._files)
36 m._files = filter(notlfile, m._files)
37 m._fmap = set(m._files)
37 m._fmap = set(m._files)
38 m._always = False
38 m._always = False
39 origmatchfn = m.matchfn
39 origmatchfn = m.matchfn
40 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
40 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
41 return m
41 return m
42 oldmatch = installmatchfn(overridematch)
42 oldmatch = installmatchfn(overridematch)
43
43
44 def installmatchfn(f):
44 def installmatchfn(f):
45 oldmatch = scmutil.match
45 oldmatch = scmutil.match
46 setattr(f, 'oldmatch', oldmatch)
46 setattr(f, 'oldmatch', oldmatch)
47 scmutil.match = f
47 scmutil.match = f
48 return oldmatch
48 return oldmatch
49
49
50 def restorematchfn():
50 def restorematchfn():
51 '''restores scmutil.match to what it was before installnormalfilesmatchfn
51 '''restores scmutil.match to what it was before installnormalfilesmatchfn
52 was called. no-op if scmutil.match is its original function.
52 was called. no-op if scmutil.match is its original function.
53
53
54 Note that n calls to installnormalfilesmatchfn will require n calls to
54 Note that n calls to installnormalfilesmatchfn will require n calls to
55 restore matchfn to reverse'''
55 restore matchfn to reverse'''
56 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
56 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
57
57
58 def addlargefiles(ui, repo, *pats, **opts):
58 def addlargefiles(ui, repo, *pats, **opts):
59 large = opts.pop('large', None)
59 large = opts.pop('large', None)
60 lfsize = lfutil.getminsize(
60 lfsize = lfutil.getminsize(
61 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
61 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
62
62
63 lfmatcher = None
63 lfmatcher = None
64 if lfutil.islfilesrepo(repo):
64 if lfutil.islfilesrepo(repo):
65 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
65 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
66 if lfpats:
66 if lfpats:
67 lfmatcher = match_.match(repo.root, '', list(lfpats))
67 lfmatcher = match_.match(repo.root, '', list(lfpats))
68
68
69 lfnames = []
69 lfnames = []
70 m = scmutil.match(repo[None], pats, opts)
70 m = scmutil.match(repo[None], pats, opts)
71 m.bad = lambda x, y: None
71 m.bad = lambda x, y: None
72 wctx = repo[None]
72 wctx = repo[None]
73 for f in repo.walk(m):
73 for f in repo.walk(m):
74 exact = m.exact(f)
74 exact = m.exact(f)
75 lfile = lfutil.standin(f) in wctx
75 lfile = lfutil.standin(f) in wctx
76 nfile = f in wctx
76 nfile = f in wctx
77 exists = lfile or nfile
77 exists = lfile or nfile
78
78
79 # Don't warn the user when they attempt to add a normal tracked file.
79 # Don't warn the user when they attempt to add a normal tracked file.
80 # The normal add code will do that for us.
80 # The normal add code will do that for us.
81 if exact and exists:
81 if exact and exists:
82 if lfile:
82 if lfile:
83 ui.warn(_('%s already a largefile\n') % f)
83 ui.warn(_('%s already a largefile\n') % f)
84 continue
84 continue
85
85
86 if (exact or not exists) and not lfutil.isstandin(f):
86 if (exact or not exists) and not lfutil.isstandin(f):
87 wfile = repo.wjoin(f)
87 wfile = repo.wjoin(f)
88
88
89 # In case the file was removed previously, but not committed
89 # In case the file was removed previously, but not committed
90 # (issue3507)
90 # (issue3507)
91 if not os.path.exists(wfile):
91 if not os.path.exists(wfile):
92 continue
92 continue
93
93
94 abovemin = (lfsize and
94 abovemin = (lfsize and
95 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
95 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
96 if large or abovemin or (lfmatcher and lfmatcher(f)):
96 if large or abovemin or (lfmatcher and lfmatcher(f)):
97 lfnames.append(f)
97 lfnames.append(f)
98 if ui.verbose or not exact:
98 if ui.verbose or not exact:
99 ui.status(_('adding %s as a largefile\n') % m.rel(f))
99 ui.status(_('adding %s as a largefile\n') % m.rel(f))
100
100
101 bad = []
101 bad = []
102 standins = []
102 standins = []
103
103
104 # Need to lock, otherwise there could be a race condition between
104 # Need to lock, otherwise there could be a race condition between
105 # when standins are created and added to the repo.
105 # when standins are created and added to the repo.
106 wlock = repo.wlock()
106 wlock = repo.wlock()
107 try:
107 try:
108 if not opts.get('dry_run'):
108 if not opts.get('dry_run'):
109 lfdirstate = lfutil.openlfdirstate(ui, repo)
109 lfdirstate = lfutil.openlfdirstate(ui, repo)
110 for f in lfnames:
110 for f in lfnames:
111 standinname = lfutil.standin(f)
111 standinname = lfutil.standin(f)
112 lfutil.writestandin(repo, standinname, hash='',
112 lfutil.writestandin(repo, standinname, hash='',
113 executable=lfutil.getexecutable(repo.wjoin(f)))
113 executable=lfutil.getexecutable(repo.wjoin(f)))
114 standins.append(standinname)
114 standins.append(standinname)
115 if lfdirstate[f] == 'r':
115 if lfdirstate[f] == 'r':
116 lfdirstate.normallookup(f)
116 lfdirstate.normallookup(f)
117 else:
117 else:
118 lfdirstate.add(f)
118 lfdirstate.add(f)
119 lfdirstate.write()
119 lfdirstate.write()
120 bad += [lfutil.splitstandin(f)
120 bad += [lfutil.splitstandin(f)
121 for f in repo[None].add(standins)
121 for f in repo[None].add(standins)
122 if f in m.files()]
122 if f in m.files()]
123 finally:
123 finally:
124 wlock.release()
124 wlock.release()
125 return bad
125 return bad
126
126
127 def removelargefiles(ui, repo, *pats, **opts):
127 def removelargefiles(ui, repo, *pats, **opts):
128 after = opts.get('after')
128 after = opts.get('after')
129 if not pats and not after:
129 if not pats and not after:
130 raise util.Abort(_('no files specified'))
130 raise util.Abort(_('no files specified'))
131 m = scmutil.match(repo[None], pats, opts)
131 m = scmutil.match(repo[None], pats, opts)
132 try:
132 try:
133 repo.lfstatus = True
133 repo.lfstatus = True
134 s = repo.status(match=m, clean=True)
134 s = repo.status(match=m, clean=True)
135 finally:
135 finally:
136 repo.lfstatus = False
136 repo.lfstatus = False
137 manifest = repo[None].manifest()
137 manifest = repo[None].manifest()
138 modified, added, deleted, clean = [[f for f in list
138 modified, added, deleted, clean = [[f for f in list
139 if lfutil.standin(f) in manifest]
139 if lfutil.standin(f) in manifest]
140 for list in [s[0], s[1], s[3], s[6]]]
140 for list in [s[0], s[1], s[3], s[6]]]
141
141
142 def warn(files, msg):
142 def warn(files, msg):
143 for f in files:
143 for f in files:
144 ui.warn(msg % m.rel(f))
144 ui.warn(msg % m.rel(f))
145 return int(len(files) > 0)
145 return int(len(files) > 0)
146
146
147 result = 0
147 result = 0
148
148
149 if after:
149 if after:
150 remove, forget = deleted, []
150 remove, forget = deleted, []
151 result = warn(modified + added + clean,
151 result = warn(modified + added + clean,
152 _('not removing %s: file still exists\n'))
152 _('not removing %s: file still exists\n'))
153 else:
153 else:
154 remove, forget = deleted + clean, []
154 remove, forget = deleted + clean, []
155 result = warn(modified, _('not removing %s: file is modified (use -f'
155 result = warn(modified, _('not removing %s: file is modified (use -f'
156 ' to force removal)\n'))
156 ' to force removal)\n'))
157 result = warn(added, _('not removing %s: file has been marked for add'
157 result = warn(added, _('not removing %s: file has been marked for add'
158 ' (use forget to undo)\n')) or result
158 ' (use forget to undo)\n')) or result
159
159
160 for f in sorted(remove + forget):
160 for f in sorted(remove + forget):
161 if ui.verbose or not m.exact(f):
161 if ui.verbose or not m.exact(f):
162 ui.status(_('removing %s\n') % m.rel(f))
162 ui.status(_('removing %s\n') % m.rel(f))
163
163
164 # Need to lock because standin files are deleted then removed from the
164 # Need to lock because standin files are deleted then removed from the
165 # repository and we could race in-between.
165 # repository and we could race in-between.
166 wlock = repo.wlock()
166 wlock = repo.wlock()
167 try:
167 try:
168 lfdirstate = lfutil.openlfdirstate(ui, repo)
168 lfdirstate = lfutil.openlfdirstate(ui, repo)
169 for f in remove:
169 for f in remove:
170 if not after:
170 if not after:
171 # If this is being called by addremove, notify the user that we
171 # If this is being called by addremove, notify the user that we
172 # are removing the file.
172 # are removing the file.
173 if getattr(repo, "_isaddremove", False):
173 if getattr(repo, "_isaddremove", False):
174 ui.status(_('removing %s\n') % f)
174 ui.status(_('removing %s\n') % f)
175 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
175 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
176 lfdirstate.remove(f)
176 lfdirstate.remove(f)
177 lfdirstate.write()
177 lfdirstate.write()
178 forget = [lfutil.standin(f) for f in forget]
178 forget = [lfutil.standin(f) for f in forget]
179 remove = [lfutil.standin(f) for f in remove]
179 remove = [lfutil.standin(f) for f in remove]
180 repo[None].forget(forget)
180 repo[None].forget(forget)
181 # If this is being called by addremove, let the original addremove
181 # If this is being called by addremove, let the original addremove
182 # function handle this.
182 # function handle this.
183 if not getattr(repo, "_isaddremove", False):
183 if not getattr(repo, "_isaddremove", False):
184 for f in remove:
184 for f in remove:
185 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
185 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
186 repo[None].forget(remove)
186 repo[None].forget(remove)
187 finally:
187 finally:
188 wlock.release()
188 wlock.release()
189
189
190 return result
190 return result
191
191
192 # For overriding mercurial.hgweb.webcommands so that largefiles will
192 # For overriding mercurial.hgweb.webcommands so that largefiles will
193 # appear at their right place in the manifests.
193 # appear at their right place in the manifests.
194 def decodepath(orig, path):
194 def decodepath(orig, path):
195 return lfutil.splitstandin(path) or path
195 return lfutil.splitstandin(path) or path
196
196
197 # -- Wrappers: modify existing commands --------------------------------
197 # -- Wrappers: modify existing commands --------------------------------
198
198
199 # Add works by going through the files that the user wanted to add and
199 # Add works by going through the files that the user wanted to add and
200 # checking if they should be added as largefiles. Then it makes a new
200 # checking if they should be added as largefiles. Then it makes a new
201 # matcher which matches only the normal files and runs the original
201 # matcher which matches only the normal files and runs the original
202 # version of add.
202 # version of add.
203 def overrideadd(orig, ui, repo, *pats, **opts):
203 def overrideadd(orig, ui, repo, *pats, **opts):
204 normal = opts.pop('normal')
204 normal = opts.pop('normal')
205 if normal:
205 if normal:
206 if opts.get('large'):
206 if opts.get('large'):
207 raise util.Abort(_('--normal cannot be used with --large'))
207 raise util.Abort(_('--normal cannot be used with --large'))
208 return orig(ui, repo, *pats, **opts)
208 return orig(ui, repo, *pats, **opts)
209 bad = addlargefiles(ui, repo, *pats, **opts)
209 bad = addlargefiles(ui, repo, *pats, **opts)
210 installnormalfilesmatchfn(repo[None].manifest())
210 installnormalfilesmatchfn(repo[None].manifest())
211 result = orig(ui, repo, *pats, **opts)
211 result = orig(ui, repo, *pats, **opts)
212 restorematchfn()
212 restorematchfn()
213
213
214 return (result == 1 or bad) and 1 or 0
214 return (result == 1 or bad) and 1 or 0
215
215
216 def overrideremove(orig, ui, repo, *pats, **opts):
216 def overrideremove(orig, ui, repo, *pats, **opts):
217 installnormalfilesmatchfn(repo[None].manifest())
217 installnormalfilesmatchfn(repo[None].manifest())
218 result = orig(ui, repo, *pats, **opts)
218 result = orig(ui, repo, *pats, **opts)
219 restorematchfn()
219 restorematchfn()
220 return removelargefiles(ui, repo, *pats, **opts) or result
220 return removelargefiles(ui, repo, *pats, **opts) or result
221
221
222 def overridestatusfn(orig, repo, rev2, **opts):
222 def overridestatusfn(orig, repo, rev2, **opts):
223 try:
223 try:
224 repo._repo.lfstatus = True
224 repo._repo.lfstatus = True
225 return orig(repo, rev2, **opts)
225 return orig(repo, rev2, **opts)
226 finally:
226 finally:
227 repo._repo.lfstatus = False
227 repo._repo.lfstatus = False
228
228
229 def overridestatus(orig, ui, repo, *pats, **opts):
229 def overridestatus(orig, ui, repo, *pats, **opts):
230 try:
230 try:
231 repo.lfstatus = True
231 repo.lfstatus = True
232 return orig(ui, repo, *pats, **opts)
232 return orig(ui, repo, *pats, **opts)
233 finally:
233 finally:
234 repo.lfstatus = False
234 repo.lfstatus = False
235
235
236 def overridedirty(orig, repo, ignoreupdate=False):
236 def overridedirty(orig, repo, ignoreupdate=False):
237 try:
237 try:
238 repo._repo.lfstatus = True
238 repo._repo.lfstatus = True
239 return orig(repo, ignoreupdate)
239 return orig(repo, ignoreupdate)
240 finally:
240 finally:
241 repo._repo.lfstatus = False
241 repo._repo.lfstatus = False
242
242
243 def overridelog(orig, ui, repo, *pats, **opts):
243 def overridelog(orig, ui, repo, *pats, **opts):
244 def overridematch(ctx, pats=[], opts={}, globbed=False,
244 def overridematch(ctx, pats=[], opts={}, globbed=False,
245 default='relpath'):
245 default='relpath'):
246 """Matcher that merges root directory with .hglf, suitable for log.
246 """Matcher that merges root directory with .hglf, suitable for log.
247 It is still possible to match .hglf directly.
247 It is still possible to match .hglf directly.
248 For any listed files run log on the standin too.
248 For any listed files run log on the standin too.
249 matchfn tries both the given filename and with .hglf stripped.
249 matchfn tries both the given filename and with .hglf stripped.
250 """
250 """
251 match = oldmatch(ctx, pats, opts, globbed, default)
251 match = oldmatch(ctx, pats, opts, globbed, default)
252 m = copy.copy(match)
252 m = copy.copy(match)
253 standins = [lfutil.standin(f) for f in m._files]
253 standins = [lfutil.standin(f) for f in m._files]
254 m._files.extend(standins)
254 m._files.extend(standins)
255 m._fmap = set(m._files)
255 m._fmap = set(m._files)
256 m._always = False
256 m._always = False
257 origmatchfn = m.matchfn
257 origmatchfn = m.matchfn
258 def lfmatchfn(f):
258 def lfmatchfn(f):
259 lf = lfutil.splitstandin(f)
259 lf = lfutil.splitstandin(f)
260 if lf is not None and origmatchfn(lf):
260 if lf is not None and origmatchfn(lf):
261 return True
261 return True
262 r = origmatchfn(f)
262 r = origmatchfn(f)
263 return r
263 return r
264 m.matchfn = lfmatchfn
264 m.matchfn = lfmatchfn
265 return m
265 return m
266 oldmatch = installmatchfn(overridematch)
266 oldmatch = installmatchfn(overridematch)
267 try:
267 try:
268 repo.lfstatus = True
268 repo.lfstatus = True
269 return orig(ui, repo, *pats, **opts)
269 return orig(ui, repo, *pats, **opts)
270 finally:
270 finally:
271 repo.lfstatus = False
271 repo.lfstatus = False
272 restorematchfn()
272 restorematchfn()
273
273
274 def overrideverify(orig, ui, repo, *pats, **opts):
274 def overrideverify(orig, ui, repo, *pats, **opts):
275 large = opts.pop('large', False)
275 large = opts.pop('large', False)
276 all = opts.pop('lfa', False)
276 all = opts.pop('lfa', False)
277 contents = opts.pop('lfc', False)
277 contents = opts.pop('lfc', False)
278
278
279 result = orig(ui, repo, *pats, **opts)
279 result = orig(ui, repo, *pats, **opts)
280 if large or all or contents:
280 if large or all or contents:
281 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
281 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
282 return result
282 return result
283
283
284 def overridedebugstate(orig, ui, repo, *pats, **opts):
284 def overridedebugstate(orig, ui, repo, *pats, **opts):
285 large = opts.pop('large', False)
285 large = opts.pop('large', False)
286 if large:
286 if large:
287 lfcommands.debugdirstate(ui, repo)
287 lfcommands.debugdirstate(ui, repo)
288 else:
288 else:
289 orig(ui, repo, *pats, **opts)
289 orig(ui, repo, *pats, **opts)
290
290
291 # Override needs to refresh standins so that update's normal merge
291 # Override needs to refresh standins so that update's normal merge
292 # will go through properly. Then the other update hook (overriding repo.update)
292 # will go through properly. Then the other update hook (overriding repo.update)
293 # will get the new files. Filemerge is also overridden so that the merge
293 # will get the new files. Filemerge is also overridden so that the merge
294 # will merge standins correctly.
294 # will merge standins correctly.
295 def overrideupdate(orig, ui, repo, *pats, **opts):
295 def overrideupdate(orig, ui, repo, *pats, **opts):
296 lfdirstate = lfutil.openlfdirstate(ui, repo)
296 lfdirstate = lfutil.openlfdirstate(ui, repo)
297 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
297 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
298 False, False)
298 False, False)
299 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
299 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
300
300
301 # Need to lock between the standins getting updated and their
301 # Need to lock between the standins getting updated and their
302 # largefiles getting updated
302 # largefiles getting updated
303 wlock = repo.wlock()
303 wlock = repo.wlock()
304 try:
304 try:
305 if opts['check']:
305 if opts['check']:
306 mod = len(modified) > 0
306 mod = len(modified) > 0
307 for lfile in unsure:
307 for lfile in unsure:
308 standin = lfutil.standin(lfile)
308 standin = lfutil.standin(lfile)
309 if repo['.'][standin].data().strip() != \
309 if repo['.'][standin].data().strip() != \
310 lfutil.hashfile(repo.wjoin(lfile)):
310 lfutil.hashfile(repo.wjoin(lfile)):
311 mod = True
311 mod = True
312 else:
312 else:
313 lfdirstate.normal(lfile)
313 lfdirstate.normal(lfile)
314 lfdirstate.write()
314 lfdirstate.write()
315 if mod:
315 if mod:
316 raise util.Abort(_('uncommitted local changes'))
316 raise util.Abort(_('uncommitted local changes'))
317 # XXX handle removed differently
317 # XXX handle removed differently
318 if not opts['clean']:
318 if not opts['clean']:
319 for lfile in unsure + modified + added:
319 for lfile in unsure + modified + added:
320 lfutil.updatestandin(repo, lfutil.standin(lfile))
320 lfutil.updatestandin(repo, lfutil.standin(lfile))
321 finally:
321 finally:
322 wlock.release()
322 wlock.release()
323 return orig(ui, repo, *pats, **opts)
323 return orig(ui, repo, *pats, **opts)
324
324
325 # Before starting the manifest merge, merge.updates will call
325 # Before starting the manifest merge, merge.updates will call
326 # _checkunknown to check if there are any files in the merged-in
326 # _checkunknown to check if there are any files in the merged-in
327 # changeset that collide with unknown files in the working copy.
327 # changeset that collide with unknown files in the working copy.
328 #
328 #
329 # The largefiles are seen as unknown, so this prevents us from merging
329 # The largefiles are seen as unknown, so this prevents us from merging
330 # in a file 'foo' if we already have a largefile with the same name.
330 # in a file 'foo' if we already have a largefile with the same name.
331 #
331 #
332 # The overridden function filters the unknown files by removing any
332 # The overridden function filters the unknown files by removing any
333 # largefiles. This makes the merge proceed and we can then handle this
333 # largefiles. This makes the merge proceed and we can then handle this
334 # case further in the overridden manifestmerge function below.
334 # case further in the overridden manifestmerge function below.
335 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
335 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
336 if lfutil.standin(f) in wctx:
336 if lfutil.standin(f) in wctx:
337 return False
337 return False
338 return origfn(repo, wctx, mctx, f)
338 return origfn(repo, wctx, mctx, f)
339
339
340 # The manifest merge handles conflicts on the manifest level. We want
340 # The manifest merge handles conflicts on the manifest level. We want
341 # to handle changes in largefile-ness of files at this level too.
341 # to handle changes in largefile-ness of files at this level too.
342 #
342 #
343 # The strategy is to run the original manifestmerge and then process
343 # The strategy is to run the original manifestmerge and then process
344 # the action list it outputs. There are two cases we need to deal with:
344 # the action list it outputs. There are two cases we need to deal with:
345 #
345 #
346 # 1. Normal file in p1, largefile in p2. Here the largefile is
346 # 1. Normal file in p1, largefile in p2. Here the largefile is
347 # detected via its standin file, which will enter the working copy
347 # detected via its standin file, which will enter the working copy
348 # with a "get" action. It is not "merge" since the standin is all
348 # with a "get" action. It is not "merge" since the standin is all
349 # Mercurial is concerned with at this level -- the link to the
349 # Mercurial is concerned with at this level -- the link to the
350 # existing normal file is not relevant here.
350 # existing normal file is not relevant here.
351 #
351 #
352 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
352 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
353 # since the largefile will be present in the working copy and
353 # since the largefile will be present in the working copy and
354 # different from the normal file in p2. Mercurial therefore
354 # different from the normal file in p2. Mercurial therefore
355 # triggers a merge action.
355 # triggers a merge action.
356 #
356 #
357 # In both cases, we prompt the user and emit new actions to either
357 # In both cases, we prompt the user and emit new actions to either
358 # remove the standin (if the normal file was kept) or to remove the
358 # remove the standin (if the normal file was kept) or to remove the
359 # normal file and get the standin (if the largefile was kept). The
359 # normal file and get the standin (if the largefile was kept). The
360 # default prompt answer is to use the largefile version since it was
360 # default prompt answer is to use the largefile version since it was
361 # presumably changed on purpose.
361 # presumably changed on purpose.
362 #
362 #
363 # Finally, the merge.applyupdates function will then take care of
363 # Finally, the merge.applyupdates function will then take care of
364 # writing the files into the working copy and lfcommands.updatelfiles
364 # writing the files into the working copy and lfcommands.updatelfiles
365 # will update the largefiles.
365 # will update the largefiles.
366 def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
366 def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
367 partial, acceptremote=False):
367 partial, acceptremote=False):
368 overwrite = force and not branchmerge
368 overwrite = force and not branchmerge
369 actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
369 actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
370 acceptremote)
370 acceptremote)
371 processed = []
371 processed = []
372
372
373 for action in actions:
373 for action in actions:
374 if overwrite:
374 if overwrite:
375 processed.append(action)
375 processed.append(action)
376 continue
376 continue
377 f, m, args, msg = action
377 f, m, args, msg = action
378
378
379 choices = (_('&Largefile'), _('&Normal file'))
379 choices = (_('&Largefile'), _('&Normal file'))
380
380
381 splitstandin = lfutil.splitstandin(f)
381 splitstandin = lfutil.splitstandin(f)
382 if (m == "g" and splitstandin is not None and
382 if (m == "g" and splitstandin is not None and
383 splitstandin in p1 and f in p2):
383 splitstandin in p1 and f in p2):
384 # Case 1: normal file in the working copy, largefile in
384 # Case 1: normal file in the working copy, largefile in
385 # the second parent
385 # the second parent
386 lfile = splitstandin
386 lfile = splitstandin
387 standin = f
387 standin = f
388 msg = _('%s has been turned into a largefile\n'
388 msg = _('%s has been turned into a largefile\n'
389 'use (l)argefile or keep as (n)ormal file?') % lfile
389 'use (l)argefile or keep as (n)ormal file?') % lfile
390 if repo.ui.promptchoice(msg, choices, 0) == 0:
390 if repo.ui.promptchoice(msg, choices, 0) == 0:
391 processed.append((lfile, "r", None, msg))
391 processed.append((lfile, "r", None, msg))
392 processed.append((standin, "g", (p2.flags(standin),), msg))
392 processed.append((standin, "g", (p2.flags(standin),), msg))
393 else:
393 else:
394 processed.append((standin, "r", None, msg))
394 processed.append((standin, "r", None, msg))
395 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
395 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
396 # Case 2: largefile in the working copy, normal file in
396 # Case 2: largefile in the working copy, normal file in
397 # the second parent
397 # the second parent
398 standin = lfutil.standin(f)
398 standin = lfutil.standin(f)
399 lfile = f
399 lfile = f
400 msg = _('%s has been turned into a normal file\n'
400 msg = _('%s has been turned into a normal file\n'
401 'keep as (l)argefile or use (n)ormal file?') % lfile
401 'keep as (l)argefile or use (n)ormal file?') % lfile
402 if repo.ui.promptchoice(msg, choices, 0) == 0:
402 if repo.ui.promptchoice(msg, choices, 0) == 0:
403 processed.append((lfile, "r", None, msg))
403 processed.append((lfile, "r", None, msg))
404 else:
404 else:
405 processed.append((standin, "r", None, msg))
405 processed.append((standin, "r", None, msg))
406 processed.append((lfile, "g", (p2.flags(lfile),), msg))
406 processed.append((lfile, "g", (p2.flags(lfile),), msg))
407 else:
407 else:
408 processed.append(action)
408 processed.append(action)
409
409
410 return processed
410 return processed
411
411
412 # Override filemerge to prompt the user about how they wish to merge
412 # Override filemerge to prompt the user about how they wish to merge
413 # largefiles. This will handle identical edits, and copy/rename +
413 # largefiles. This will handle identical edits, and copy/rename +
414 # edit without prompting the user.
414 # edit without prompting the user.
415 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
415 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
416 # Use better variable names here. Because this is a wrapper we cannot
416 # Use better variable names here. Because this is a wrapper we cannot
417 # change the variable names in the function declaration.
417 # change the variable names in the function declaration.
418 fcdest, fcother, fcancestor = fcd, fco, fca
418 fcdest, fcother, fcancestor = fcd, fco, fca
419 if not lfutil.isstandin(orig):
419 if not lfutil.isstandin(orig):
420 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
420 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
421 else:
421 else:
422 if not fcother.cmp(fcdest): # files identical?
422 if not fcother.cmp(fcdest): # files identical?
423 return None
423 return None
424
424
425 # backwards, use working dir parent as ancestor
425 # backwards, use working dir parent as ancestor
426 if fcancestor == fcother:
426 if fcancestor == fcother:
427 fcancestor = fcdest.parents()[0]
427 fcancestor = fcdest.parents()[0]
428
428
429 if orig != fcother.path():
429 if orig != fcother.path():
430 repo.ui.status(_('merging %s and %s to %s\n')
430 repo.ui.status(_('merging %s and %s to %s\n')
431 % (lfutil.splitstandin(orig),
431 % (lfutil.splitstandin(orig),
432 lfutil.splitstandin(fcother.path()),
432 lfutil.splitstandin(fcother.path()),
433 lfutil.splitstandin(fcdest.path())))
433 lfutil.splitstandin(fcdest.path())))
434 else:
434 else:
435 repo.ui.status(_('merging %s\n')
435 repo.ui.status(_('merging %s\n')
436 % lfutil.splitstandin(fcdest.path()))
436 % lfutil.splitstandin(fcdest.path()))
437
437
438 if fcancestor.path() != fcother.path() and fcother.data() == \
438 if fcancestor.path() != fcother.path() and fcother.data() == \
439 fcancestor.data():
439 fcancestor.data():
440 return 0
440 return 0
441 if fcancestor.path() != fcdest.path() and fcdest.data() == \
441 if fcancestor.path() != fcdest.path() and fcdest.data() == \
442 fcancestor.data():
442 fcancestor.data():
443 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
443 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
444 return 0
444 return 0
445
445
446 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
446 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
447 'keep (l)ocal or take (o)ther?') %
447 'keep (l)ocal or take (o)ther?') %
448 lfutil.splitstandin(orig),
448 lfutil.splitstandin(orig),
449 (_('&Local'), _('&Other')), 0) == 0:
449 (_('&Local'), _('&Other')), 0) == 0:
450 return 0
450 return 0
451 else:
451 else:
452 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
452 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
453 return 0
453 return 0
454
454
455 # Copy first changes the matchers to match standins instead of
455 # Copy first changes the matchers to match standins instead of
456 # largefiles. Then it overrides util.copyfile in that function it
456 # largefiles. Then it overrides util.copyfile in that function it
457 # checks if the destination largefile already exists. It also keeps a
457 # checks if the destination largefile already exists. It also keeps a
458 # list of copied files so that the largefiles can be copied and the
458 # list of copied files so that the largefiles can be copied and the
459 # dirstate updated.
459 # dirstate updated.
460 def overridecopy(orig, ui, repo, pats, opts, rename=False):
460 def overridecopy(orig, ui, repo, pats, opts, rename=False):
461 # doesn't remove largefile on rename
461 # doesn't remove largefile on rename
462 if len(pats) < 2:
462 if len(pats) < 2:
463 # this isn't legal, let the original function deal with it
463 # this isn't legal, let the original function deal with it
464 return orig(ui, repo, pats, opts, rename)
464 return orig(ui, repo, pats, opts, rename)
465
465
466 def makestandin(relpath):
466 def makestandin(relpath):
467 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
467 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
468 return os.path.join(repo.wjoin(lfutil.standin(path)))
468 return os.path.join(repo.wjoin(lfutil.standin(path)))
469
469
470 fullpats = scmutil.expandpats(pats)
470 fullpats = scmutil.expandpats(pats)
471 dest = fullpats[-1]
471 dest = fullpats[-1]
472
472
473 if os.path.isdir(dest):
473 if os.path.isdir(dest):
474 if not os.path.isdir(makestandin(dest)):
474 if not os.path.isdir(makestandin(dest)):
475 os.makedirs(makestandin(dest))
475 os.makedirs(makestandin(dest))
476 # This could copy both lfiles and normal files in one command,
476 # This could copy both lfiles and normal files in one command,
477 # but we don't want to do that. First replace their matcher to
477 # but we don't want to do that. First replace their matcher to
478 # only match normal files and run it, then replace it to just
478 # only match normal files and run it, then replace it to just
479 # match largefiles and run it again.
479 # match largefiles and run it again.
480 nonormalfiles = False
480 nonormalfiles = False
481 nolfiles = False
481 nolfiles = False
482 try:
482 try:
483 try:
483 try:
484 installnormalfilesmatchfn(repo[None].manifest())
484 installnormalfilesmatchfn(repo[None].manifest())
485 result = orig(ui, repo, pats, opts, rename)
485 result = orig(ui, repo, pats, opts, rename)
486 except util.Abort, e:
486 except util.Abort, e:
487 if str(e) != _('no files to copy'):
487 if str(e) != _('no files to copy'):
488 raise e
488 raise e
489 else:
489 else:
490 nonormalfiles = True
490 nonormalfiles = True
491 result = 0
491 result = 0
492 finally:
492 finally:
493 restorematchfn()
493 restorematchfn()
494
494
495 # The first rename can cause our current working directory to be removed.
495 # The first rename can cause our current working directory to be removed.
496 # In that case there is nothing left to copy/rename so just quit.
496 # In that case there is nothing left to copy/rename so just quit.
497 try:
497 try:
498 repo.getcwd()
498 repo.getcwd()
499 except OSError:
499 except OSError:
500 return result
500 return result
501
501
502 try:
502 try:
503 try:
503 try:
504 # When we call orig below it creates the standins but we don't add
504 # When we call orig below it creates the standins but we don't add
505 # them to the dir state until later so lock during that time.
505 # them to the dir state until later so lock during that time.
506 wlock = repo.wlock()
506 wlock = repo.wlock()
507
507
508 manifest = repo[None].manifest()
508 manifest = repo[None].manifest()
509 oldmatch = None # for the closure
509 oldmatch = None # for the closure
510 def overridematch(ctx, pats=[], opts={}, globbed=False,
510 def overridematch(ctx, pats=[], opts={}, globbed=False,
511 default='relpath'):
511 default='relpath'):
512 newpats = []
512 newpats = []
513 # The patterns were previously mangled to add the standin
513 # The patterns were previously mangled to add the standin
514 # directory; we need to remove that now
514 # directory; we need to remove that now
515 for pat in pats:
515 for pat in pats:
516 if match_.patkind(pat) is None and lfutil.shortname in pat:
516 if match_.patkind(pat) is None and lfutil.shortname in pat:
517 newpats.append(pat.replace(lfutil.shortname, ''))
517 newpats.append(pat.replace(lfutil.shortname, ''))
518 else:
518 else:
519 newpats.append(pat)
519 newpats.append(pat)
520 match = oldmatch(ctx, newpats, opts, globbed, default)
520 match = oldmatch(ctx, newpats, opts, globbed, default)
521 m = copy.copy(match)
521 m = copy.copy(match)
522 lfile = lambda f: lfutil.standin(f) in manifest
522 lfile = lambda f: lfutil.standin(f) in manifest
523 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
523 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
524 m._fmap = set(m._files)
524 m._fmap = set(m._files)
525 m._always = False
525 m._always = False
526 origmatchfn = m.matchfn
526 origmatchfn = m.matchfn
527 m.matchfn = lambda f: (lfutil.isstandin(f) and
527 m.matchfn = lambda f: (lfutil.isstandin(f) and
528 (f in manifest) and
528 (f in manifest) and
529 origmatchfn(lfutil.splitstandin(f)) or
529 origmatchfn(lfutil.splitstandin(f)) or
530 None)
530 None)
531 return m
531 return m
532 oldmatch = installmatchfn(overridematch)
532 oldmatch = installmatchfn(overridematch)
533 listpats = []
533 listpats = []
534 for pat in pats:
534 for pat in pats:
535 if match_.patkind(pat) is not None:
535 if match_.patkind(pat) is not None:
536 listpats.append(pat)
536 listpats.append(pat)
537 else:
537 else:
538 listpats.append(makestandin(pat))
538 listpats.append(makestandin(pat))
539
539
540 try:
540 try:
541 origcopyfile = util.copyfile
541 origcopyfile = util.copyfile
542 copiedfiles = []
542 copiedfiles = []
543 def overridecopyfile(src, dest):
543 def overridecopyfile(src, dest):
544 if (lfutil.shortname in src and
544 if (lfutil.shortname in src and
545 dest.startswith(repo.wjoin(lfutil.shortname))):
545 dest.startswith(repo.wjoin(lfutil.shortname))):
546 destlfile = dest.replace(lfutil.shortname, '')
546 destlfile = dest.replace(lfutil.shortname, '')
547 if not opts['force'] and os.path.exists(destlfile):
547 if not opts['force'] and os.path.exists(destlfile):
548 raise IOError('',
548 raise IOError('',
549 _('destination largefile already exists'))
549 _('destination largefile already exists'))
550 copiedfiles.append((src, dest))
550 copiedfiles.append((src, dest))
551 origcopyfile(src, dest)
551 origcopyfile(src, dest)
552
552
553 util.copyfile = overridecopyfile
553 util.copyfile = overridecopyfile
554 result += orig(ui, repo, listpats, opts, rename)
554 result += orig(ui, repo, listpats, opts, rename)
555 finally:
555 finally:
556 util.copyfile = origcopyfile
556 util.copyfile = origcopyfile
557
557
558 lfdirstate = lfutil.openlfdirstate(ui, repo)
558 lfdirstate = lfutil.openlfdirstate(ui, repo)
559 for (src, dest) in copiedfiles:
559 for (src, dest) in copiedfiles:
560 if (lfutil.shortname in src and
560 if (lfutil.shortname in src and
561 dest.startswith(repo.wjoin(lfutil.shortname))):
561 dest.startswith(repo.wjoin(lfutil.shortname))):
562 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
562 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
563 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
563 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
564 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
564 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
565 if not os.path.isdir(destlfiledir):
565 if not os.path.isdir(destlfiledir):
566 os.makedirs(destlfiledir)
566 os.makedirs(destlfiledir)
567 if rename:
567 if rename:
568 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
568 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
569 lfdirstate.remove(srclfile)
569 lfdirstate.remove(srclfile)
570 else:
570 else:
571 util.copyfile(repo.wjoin(srclfile),
571 util.copyfile(repo.wjoin(srclfile),
572 repo.wjoin(destlfile))
572 repo.wjoin(destlfile))
573
573
574 lfdirstate.add(destlfile)
574 lfdirstate.add(destlfile)
575 lfdirstate.write()
575 lfdirstate.write()
576 except util.Abort, e:
576 except util.Abort, e:
577 if str(e) != _('no files to copy'):
577 if str(e) != _('no files to copy'):
578 raise e
578 raise e
579 else:
579 else:
580 nolfiles = True
580 nolfiles = True
581 finally:
581 finally:
582 restorematchfn()
582 restorematchfn()
583 wlock.release()
583 wlock.release()
584
584
585 if nolfiles and nonormalfiles:
585 if nolfiles and nonormalfiles:
586 raise util.Abort(_('no files to copy'))
586 raise util.Abort(_('no files to copy'))
587
587
588 return result
588 return result
589
589
590 # When the user calls revert, we have to be careful to not revert any
590 # When the user calls revert, we have to be careful to not revert any
591 # changes to other largefiles accidentally. This means we have to keep
591 # changes to other largefiles accidentally. This means we have to keep
592 # track of the largefiles that are being reverted so we only pull down
592 # track of the largefiles that are being reverted so we only pull down
593 # the necessary largefiles.
593 # the necessary largefiles.
594 #
594 #
595 # Standins are only updated (to match the hash of largefiles) before
595 # Standins are only updated (to match the hash of largefiles) before
596 # commits. Update the standins then run the original revert, changing
596 # commits. Update the standins then run the original revert, changing
597 # the matcher to hit standins instead of largefiles. Based on the
597 # the matcher to hit standins instead of largefiles. Based on the
598 # resulting standins update the largefiles. Then return the standins
598 # resulting standins update the largefiles. Then return the standins
599 # to their proper state
599 # to their proper state
600 def overriderevert(orig, ui, repo, *pats, **opts):
600 def overriderevert(orig, ui, repo, *pats, **opts):
601 # Because we put the standins in a bad state (by updating them)
601 # Because we put the standins in a bad state (by updating them)
602 # and then return them to a correct state we need to lock to
602 # and then return them to a correct state we need to lock to
603 # prevent others from changing them in their incorrect state.
603 # prevent others from changing them in their incorrect state.
604 wlock = repo.wlock()
604 wlock = repo.wlock()
605 try:
605 try:
606 lfdirstate = lfutil.openlfdirstate(ui, repo)
606 lfdirstate = lfutil.openlfdirstate(ui, repo)
607 (modified, added, removed, missing, unknown, ignored, clean) = \
607 (modified, added, removed, missing, unknown, ignored, clean) = \
608 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
608 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
609 lfdirstate.write()
609 lfdirstate.write()
610 for lfile in modified:
610 for lfile in modified:
611 lfutil.updatestandin(repo, lfutil.standin(lfile))
611 lfutil.updatestandin(repo, lfutil.standin(lfile))
612 for lfile in missing:
612 for lfile in missing:
613 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
613 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
614 os.unlink(repo.wjoin(lfutil.standin(lfile)))
614 os.unlink(repo.wjoin(lfutil.standin(lfile)))
615
615
616 try:
616 try:
617 ctx = scmutil.revsingle(repo, opts.get('rev'))
617 ctx = scmutil.revsingle(repo, opts.get('rev'))
618 oldmatch = None # for the closure
618 oldmatch = None # for the closure
619 def overridematch(ctx, pats=[], opts={}, globbed=False,
619 def overridematch(ctx, pats=[], opts={}, globbed=False,
620 default='relpath'):
620 default='relpath'):
621 match = oldmatch(ctx, pats, opts, globbed, default)
621 match = oldmatch(ctx, pats, opts, globbed, default)
622 m = copy.copy(match)
622 m = copy.copy(match)
623 def tostandin(f):
623 def tostandin(f):
624 if lfutil.standin(f) in ctx:
624 if lfutil.standin(f) in ctx:
625 return lfutil.standin(f)
625 return lfutil.standin(f)
626 elif lfutil.standin(f) in repo[None]:
626 elif lfutil.standin(f) in repo[None]:
627 return None
627 return None
628 return f
628 return f
629 m._files = [tostandin(f) for f in m._files]
629 m._files = [tostandin(f) for f in m._files]
630 m._files = [f for f in m._files if f is not None]
630 m._files = [f for f in m._files if f is not None]
631 m._fmap = set(m._files)
631 m._fmap = set(m._files)
632 m._always = False
632 m._always = False
633 origmatchfn = m.matchfn
633 origmatchfn = m.matchfn
634 def matchfn(f):
634 def matchfn(f):
635 if lfutil.isstandin(f):
635 if lfutil.isstandin(f):
636 # We need to keep track of what largefiles are being
636 # We need to keep track of what largefiles are being
637 # matched so we know which ones to update later --
637 # matched so we know which ones to update later --
638 # otherwise we accidentally revert changes to other
638 # otherwise we accidentally revert changes to other
639 # largefiles. This is repo-specific, so duckpunch the
639 # largefiles. This is repo-specific, so duckpunch the
640 # repo object to keep the list of largefiles for us
640 # repo object to keep the list of largefiles for us
641 # later.
641 # later.
642 if origmatchfn(lfutil.splitstandin(f)) and \
642 if origmatchfn(lfutil.splitstandin(f)) and \
643 (f in repo[None] or f in ctx):
643 (f in repo[None] or f in ctx):
644 lfileslist = getattr(repo, '_lfilestoupdate', [])
644 lfileslist = getattr(repo, '_lfilestoupdate', [])
645 lfileslist.append(lfutil.splitstandin(f))
645 lfileslist.append(lfutil.splitstandin(f))
646 repo._lfilestoupdate = lfileslist
646 repo._lfilestoupdate = lfileslist
647 return True
647 return True
648 else:
648 else:
649 return False
649 return False
650 return origmatchfn(f)
650 return origmatchfn(f)
651 m.matchfn = matchfn
651 m.matchfn = matchfn
652 return m
652 return m
653 oldmatch = installmatchfn(overridematch)
653 oldmatch = installmatchfn(overridematch)
654 scmutil.match
654 scmutil.match
655 matches = overridematch(repo[None], pats, opts)
655 matches = overridematch(repo[None], pats, opts)
656 orig(ui, repo, *pats, **opts)
656 orig(ui, repo, *pats, **opts)
657 finally:
657 finally:
658 restorematchfn()
658 restorematchfn()
659 lfileslist = getattr(repo, '_lfilestoupdate', [])
659 lfileslist = getattr(repo, '_lfilestoupdate', [])
660 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
660 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
661 printmessage=False)
661 printmessage=False)
662
662
663 # empty out the largefiles list so we start fresh next time
663 # empty out the largefiles list so we start fresh next time
664 repo._lfilestoupdate = []
664 repo._lfilestoupdate = []
665 for lfile in modified:
665 for lfile in modified:
666 if lfile in lfileslist:
666 if lfile in lfileslist:
667 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
667 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
668 in repo['.']:
668 in repo['.']:
669 lfutil.writestandin(repo, lfutil.standin(lfile),
669 lfutil.writestandin(repo, lfutil.standin(lfile),
670 repo['.'][lfile].data().strip(),
670 repo['.'][lfile].data().strip(),
671 'x' in repo['.'][lfile].flags())
671 'x' in repo['.'][lfile].flags())
672 lfdirstate = lfutil.openlfdirstate(ui, repo)
672 lfdirstate = lfutil.openlfdirstate(ui, repo)
673 for lfile in added:
673 for lfile in added:
674 standin = lfutil.standin(lfile)
674 standin = lfutil.standin(lfile)
675 if standin not in ctx and (standin in matches or opts.get('all')):
675 if standin not in ctx and (standin in matches or opts.get('all')):
676 if lfile in lfdirstate:
676 if lfile in lfdirstate:
677 lfdirstate.drop(lfile)
677 lfdirstate.drop(lfile)
678 util.unlinkpath(repo.wjoin(standin))
678 util.unlinkpath(repo.wjoin(standin))
679 lfdirstate.write()
679 lfdirstate.write()
680 finally:
680 finally:
681 wlock.release()
681 wlock.release()
682
682
683 def hgupdaterepo(orig, repo, node, overwrite):
683 def hgupdaterepo(orig, repo, node, overwrite):
684 if not overwrite:
684 if not overwrite:
685 # Only call updatelfiles on the standins that have changed to save time
685 # Only call updatelfiles on the standins that have changed to save time
686 oldstandins = lfutil.getstandinsstate(repo)
686 oldstandins = lfutil.getstandinsstate(repo)
687
687
688 result = orig(repo, node, overwrite)
688 result = orig(repo, node, overwrite)
689
689
690 filelist = None
690 filelist = None
691 if not overwrite:
691 if not overwrite:
692 newstandins = lfutil.getstandinsstate(repo)
692 newstandins = lfutil.getstandinsstate(repo)
693 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
693 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
694 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
694 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
695 return result
695 return result
696
696
697 def hgmerge(orig, repo, node, force=None, remind=True):
697 def hgmerge(orig, repo, node, force=None, remind=True):
698 result = orig(repo, node, force, remind)
698 result = orig(repo, node, force, remind)
699 lfcommands.updatelfiles(repo.ui, repo)
699 lfcommands.updatelfiles(repo.ui, repo)
700 return result
700 return result
701
701
702 # When we rebase a repository with remotely changed largefiles, we need to
702 # When we rebase a repository with remotely changed largefiles, we need to
703 # take some extra care so that the largefiles are correctly updated in the
703 # take some extra care so that the largefiles are correctly updated in the
704 # working copy
704 # working copy
705 def overridepull(orig, ui, repo, source=None, **opts):
705 def overridepull(orig, ui, repo, source=None, **opts):
706 revsprepull = len(repo)
706 revsprepull = len(repo)
707 if not source:
707 if not source:
708 source = 'default'
708 source = 'default'
709 repo.lfpullsource = source
709 repo.lfpullsource = source
710 if opts.get('rebase', False):
710 if opts.get('rebase', False):
711 repo._isrebasing = True
711 repo._isrebasing = True
712 try:
712 try:
713 if opts.get('update'):
713 if opts.get('update'):
714 del opts['update']
714 del opts['update']
715 ui.debug('--update and --rebase are not compatible, ignoring '
715 ui.debug('--update and --rebase are not compatible, ignoring '
716 'the update flag\n')
716 'the update flag\n')
717 del opts['rebase']
717 del opts['rebase']
718 cmdutil.bailifchanged(repo)
718 cmdutil.bailifchanged(repo)
719 origpostincoming = commands.postincoming
719 origpostincoming = commands.postincoming
720 def _dummy(*args, **kwargs):
720 def _dummy(*args, **kwargs):
721 pass
721 pass
722 commands.postincoming = _dummy
722 commands.postincoming = _dummy
723 try:
723 try:
724 result = commands.pull(ui, repo, source, **opts)
724 result = commands.pull(ui, repo, source, **opts)
725 finally:
725 finally:
726 commands.postincoming = origpostincoming
726 commands.postincoming = origpostincoming
727 revspostpull = len(repo)
727 revspostpull = len(repo)
728 if revspostpull > revsprepull:
728 if revspostpull > revsprepull:
729 result = result or rebase.rebase(ui, repo)
729 result = result or rebase.rebase(ui, repo)
730 finally:
730 finally:
731 repo._isrebasing = False
731 repo._isrebasing = False
732 else:
732 else:
733 oldheads = lfutil.getcurrentheads(repo)
734 result = orig(ui, repo, source, **opts)
733 result = orig(ui, repo, source, **opts)
735 if opts.get('cache_largefiles'):
736 # If you are pulling from a remote location that is not your
737 # default location, you may want to cache largefiles for new heads
738 # that have been pulled, so you can easily merge or rebase with
739 # them later
740 numcached = 0
741 heads = lfutil.getcurrentheads(repo)
742 newheads = set(heads).difference(set(oldheads))
743 if len(newheads) > 0:
744 ui.status(_("caching largefiles for %s heads\n") %
745 len(newheads))
746 for head in newheads:
747 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
748 numcached += len(cached)
749 ui.status(_("%d largefiles cached\n") % numcached)
750 revspostpull = len(repo)
734 revspostpull = len(repo)
751 if opts.get('all_largefiles'):
735 if opts.get('all_largefiles'):
752 revs = []
736 revs = []
753 for rev in xrange(revsprepull, revspostpull):
737 for rev in xrange(revsprepull, revspostpull):
754 revs.append(repo[rev].rev())
738 revs.append(repo[rev].rev())
755 lfcommands.downloadlfiles(ui, repo, revs)
739 lfcommands.downloadlfiles(ui, repo, revs)
756 lfrevs = opts.get('lfrev', [])
740 lfrevs = opts.get('lfrev', [])
757 if lfrevs and revspostpull > revsprepull:
741 if lfrevs and revspostpull > revsprepull:
758 numcached = 0
742 numcached = 0
759 repo.firstpulled = revsprepull # for pulled() revset expression
743 repo.firstpulled = revsprepull # for pulled() revset expression
760 try:
744 try:
761 for rev in scmutil.revrange(repo, lfrevs):
745 for rev in scmutil.revrange(repo, lfrevs):
762 ui.note(_('pulling largefiles for revision %s\n') % rev)
746 ui.note(_('pulling largefiles for revision %s\n') % rev)
763 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
747 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
764 numcached += len(cached)
748 numcached += len(cached)
765 finally:
749 finally:
766 del repo.firstpulled
750 del repo.firstpulled
767 ui.status(_("%d largefiles cached\n") % numcached)
751 ui.status(_("%d largefiles cached\n") % numcached)
768 return result
752 return result
769
753
770 def pulledrevsetsymbol(repo, subset, x):
754 def pulledrevsetsymbol(repo, subset, x):
771 """``pulled()``
755 """``pulled()``
772 Changesets that just has been pulled.
756 Changesets that just has been pulled.
773
757
774 Only available with largefiles from pull --lfrev expressions.
758 Only available with largefiles from pull --lfrev expressions.
775
759
776 .. container:: verbose
760 .. container:: verbose
777
761
778 Some examples:
762 Some examples:
779
763
780 - pull largefiles for all new changesets::
764 - pull largefiles for all new changesets::
781
765
782 hg pull -lfrev "pulled()"
766 hg pull -lfrev "pulled()"
783
767
784 - pull largefiles for all new branch heads::
768 - pull largefiles for all new branch heads::
785
769
786 hg pull -lfrev "head(pulled()) and not closed()"
770 hg pull -lfrev "head(pulled()) and not closed()"
787
771
788 """
772 """
789
773
790 try:
774 try:
791 firstpulled = repo.firstpulled
775 firstpulled = repo.firstpulled
792 except AttributeError:
776 except AttributeError:
793 raise util.Abort(_("pulled() only available in --lfrev"))
777 raise util.Abort(_("pulled() only available in --lfrev"))
794 return [r for r in subset if r >= firstpulled]
778 return [r for r in subset if r >= firstpulled]
795
779
796 def overrideclone(orig, ui, source, dest=None, **opts):
780 def overrideclone(orig, ui, source, dest=None, **opts):
797 d = dest
781 d = dest
798 if d is None:
782 if d is None:
799 d = hg.defaultdest(source)
783 d = hg.defaultdest(source)
800 if opts.get('all_largefiles') and not hg.islocal(d):
784 if opts.get('all_largefiles') and not hg.islocal(d):
801 raise util.Abort(_(
785 raise util.Abort(_(
802 '--all-largefiles is incompatible with non-local destination %s' %
786 '--all-largefiles is incompatible with non-local destination %s' %
803 d))
787 d))
804
788
805 return orig(ui, source, dest, **opts)
789 return orig(ui, source, dest, **opts)
806
790
807 def hgclone(orig, ui, opts, *args, **kwargs):
791 def hgclone(orig, ui, opts, *args, **kwargs):
808 result = orig(ui, opts, *args, **kwargs)
792 result = orig(ui, opts, *args, **kwargs)
809
793
810 if result is not None:
794 if result is not None:
811 sourcerepo, destrepo = result
795 sourcerepo, destrepo = result
812 repo = destrepo.local()
796 repo = destrepo.local()
813
797
814 # Caching is implicitly limited to 'rev' option, since the dest repo was
798 # Caching is implicitly limited to 'rev' option, since the dest repo was
815 # truncated at that point. The user may expect a download count with
799 # truncated at that point. The user may expect a download count with
816 # this option, so attempt whether or not this is a largefile repo.
800 # this option, so attempt whether or not this is a largefile repo.
817 if opts.get('all_largefiles'):
801 if opts.get('all_largefiles'):
818 success, missing = lfcommands.downloadlfiles(ui, repo, None)
802 success, missing = lfcommands.downloadlfiles(ui, repo, None)
819
803
820 if missing != 0:
804 if missing != 0:
821 return None
805 return None
822
806
823 return result
807 return result
824
808
825 def overriderebase(orig, ui, repo, **opts):
809 def overriderebase(orig, ui, repo, **opts):
826 repo._isrebasing = True
810 repo._isrebasing = True
827 try:
811 try:
828 return orig(ui, repo, **opts)
812 return orig(ui, repo, **opts)
829 finally:
813 finally:
830 repo._isrebasing = False
814 repo._isrebasing = False
831
815
832 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
816 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
833 prefix=None, mtime=None, subrepos=None):
817 prefix=None, mtime=None, subrepos=None):
834 # No need to lock because we are only reading history and
818 # No need to lock because we are only reading history and
835 # largefile caches, neither of which are modified.
819 # largefile caches, neither of which are modified.
836 lfcommands.cachelfiles(repo.ui, repo, node)
820 lfcommands.cachelfiles(repo.ui, repo, node)
837
821
838 if kind not in archival.archivers:
822 if kind not in archival.archivers:
839 raise util.Abort(_("unknown archive type '%s'") % kind)
823 raise util.Abort(_("unknown archive type '%s'") % kind)
840
824
841 ctx = repo[node]
825 ctx = repo[node]
842
826
843 if kind == 'files':
827 if kind == 'files':
844 if prefix:
828 if prefix:
845 raise util.Abort(
829 raise util.Abort(
846 _('cannot give prefix when archiving to files'))
830 _('cannot give prefix when archiving to files'))
847 else:
831 else:
848 prefix = archival.tidyprefix(dest, kind, prefix)
832 prefix = archival.tidyprefix(dest, kind, prefix)
849
833
850 def write(name, mode, islink, getdata):
834 def write(name, mode, islink, getdata):
851 if matchfn and not matchfn(name):
835 if matchfn and not matchfn(name):
852 return
836 return
853 data = getdata()
837 data = getdata()
854 if decode:
838 if decode:
855 data = repo.wwritedata(name, data)
839 data = repo.wwritedata(name, data)
856 archiver.addfile(prefix + name, mode, islink, data)
840 archiver.addfile(prefix + name, mode, islink, data)
857
841
858 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
842 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
859
843
860 if repo.ui.configbool("ui", "archivemeta", True):
844 if repo.ui.configbool("ui", "archivemeta", True):
861 def metadata():
845 def metadata():
862 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
846 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
863 hex(repo.changelog.node(0)), hex(node), ctx.branch())
847 hex(repo.changelog.node(0)), hex(node), ctx.branch())
864
848
865 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
849 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
866 if repo.tagtype(t) == 'global')
850 if repo.tagtype(t) == 'global')
867 if not tags:
851 if not tags:
868 repo.ui.pushbuffer()
852 repo.ui.pushbuffer()
869 opts = {'template': '{latesttag}\n{latesttagdistance}',
853 opts = {'template': '{latesttag}\n{latesttagdistance}',
870 'style': '', 'patch': None, 'git': None}
854 'style': '', 'patch': None, 'git': None}
871 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
855 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
872 ltags, dist = repo.ui.popbuffer().split('\n')
856 ltags, dist = repo.ui.popbuffer().split('\n')
873 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
857 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
874 tags += 'latesttagdistance: %s\n' % dist
858 tags += 'latesttagdistance: %s\n' % dist
875
859
876 return base + tags
860 return base + tags
877
861
878 write('.hg_archival.txt', 0644, False, metadata)
862 write('.hg_archival.txt', 0644, False, metadata)
879
863
880 for f in ctx:
864 for f in ctx:
881 ff = ctx.flags(f)
865 ff = ctx.flags(f)
882 getdata = ctx[f].data
866 getdata = ctx[f].data
883 if lfutil.isstandin(f):
867 if lfutil.isstandin(f):
884 path = lfutil.findfile(repo, getdata().strip())
868 path = lfutil.findfile(repo, getdata().strip())
885 if path is None:
869 if path is None:
886 raise util.Abort(
870 raise util.Abort(
887 _('largefile %s not found in repo store or system cache')
871 _('largefile %s not found in repo store or system cache')
888 % lfutil.splitstandin(f))
872 % lfutil.splitstandin(f))
889 f = lfutil.splitstandin(f)
873 f = lfutil.splitstandin(f)
890
874
891 def getdatafn():
875 def getdatafn():
892 fd = None
876 fd = None
893 try:
877 try:
894 fd = open(path, 'rb')
878 fd = open(path, 'rb')
895 return fd.read()
879 return fd.read()
896 finally:
880 finally:
897 if fd:
881 if fd:
898 fd.close()
882 fd.close()
899
883
900 getdata = getdatafn
884 getdata = getdatafn
901 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
885 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
902
886
903 if subrepos:
887 if subrepos:
904 for subpath in sorted(ctx.substate):
888 for subpath in sorted(ctx.substate):
905 sub = ctx.sub(subpath)
889 sub = ctx.sub(subpath)
906 submatch = match_.narrowmatcher(subpath, matchfn)
890 submatch = match_.narrowmatcher(subpath, matchfn)
907 sub.archive(repo.ui, archiver, prefix, submatch)
891 sub.archive(repo.ui, archiver, prefix, submatch)
908
892
909 archiver.done()
893 archiver.done()
910
894
911 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
895 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
912 repo._get(repo._state + ('hg',))
896 repo._get(repo._state + ('hg',))
913 rev = repo._state[1]
897 rev = repo._state[1]
914 ctx = repo._repo[rev]
898 ctx = repo._repo[rev]
915
899
916 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
900 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
917
901
918 def write(name, mode, islink, getdata):
902 def write(name, mode, islink, getdata):
919 # At this point, the standin has been replaced with the largefile name,
903 # At this point, the standin has been replaced with the largefile name,
920 # so the normal matcher works here without the lfutil variants.
904 # so the normal matcher works here without the lfutil variants.
921 if match and not match(f):
905 if match and not match(f):
922 return
906 return
923 data = getdata()
907 data = getdata()
924
908
925 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
909 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
926
910
927 for f in ctx:
911 for f in ctx:
928 ff = ctx.flags(f)
912 ff = ctx.flags(f)
929 getdata = ctx[f].data
913 getdata = ctx[f].data
930 if lfutil.isstandin(f):
914 if lfutil.isstandin(f):
931 path = lfutil.findfile(repo._repo, getdata().strip())
915 path = lfutil.findfile(repo._repo, getdata().strip())
932 if path is None:
916 if path is None:
933 raise util.Abort(
917 raise util.Abort(
934 _('largefile %s not found in repo store or system cache')
918 _('largefile %s not found in repo store or system cache')
935 % lfutil.splitstandin(f))
919 % lfutil.splitstandin(f))
936 f = lfutil.splitstandin(f)
920 f = lfutil.splitstandin(f)
937
921
938 def getdatafn():
922 def getdatafn():
939 fd = None
923 fd = None
940 try:
924 try:
941 fd = open(os.path.join(prefix, path), 'rb')
925 fd = open(os.path.join(prefix, path), 'rb')
942 return fd.read()
926 return fd.read()
943 finally:
927 finally:
944 if fd:
928 if fd:
945 fd.close()
929 fd.close()
946
930
947 getdata = getdatafn
931 getdata = getdatafn
948
932
949 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
933 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
950
934
951 for subpath in sorted(ctx.substate):
935 for subpath in sorted(ctx.substate):
952 sub = ctx.sub(subpath)
936 sub = ctx.sub(subpath)
953 submatch = match_.narrowmatcher(subpath, match)
937 submatch = match_.narrowmatcher(subpath, match)
954 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
938 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
955 submatch)
939 submatch)
956
940
957 # If a largefile is modified, the change is not reflected in its
941 # If a largefile is modified, the change is not reflected in its
958 # standin until a commit. cmdutil.bailifchanged() raises an exception
942 # standin until a commit. cmdutil.bailifchanged() raises an exception
959 # if the repo has uncommitted changes. Wrap it to also check if
943 # if the repo has uncommitted changes. Wrap it to also check if
960 # largefiles were changed. This is used by bisect and backout.
944 # largefiles were changed. This is used by bisect and backout.
961 def overridebailifchanged(orig, repo):
945 def overridebailifchanged(orig, repo):
962 orig(repo)
946 orig(repo)
963 repo.lfstatus = True
947 repo.lfstatus = True
964 modified, added, removed, deleted = repo.status()[:4]
948 modified, added, removed, deleted = repo.status()[:4]
965 repo.lfstatus = False
949 repo.lfstatus = False
966 if modified or added or removed or deleted:
950 if modified or added or removed or deleted:
967 raise util.Abort(_('outstanding uncommitted changes'))
951 raise util.Abort(_('outstanding uncommitted changes'))
968
952
969 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
953 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
970 def overridefetch(orig, ui, repo, *pats, **opts):
954 def overridefetch(orig, ui, repo, *pats, **opts):
971 repo.lfstatus = True
955 repo.lfstatus = True
972 modified, added, removed, deleted = repo.status()[:4]
956 modified, added, removed, deleted = repo.status()[:4]
973 repo.lfstatus = False
957 repo.lfstatus = False
974 if modified or added or removed or deleted:
958 if modified or added or removed or deleted:
975 raise util.Abort(_('outstanding uncommitted changes'))
959 raise util.Abort(_('outstanding uncommitted changes'))
976 return orig(ui, repo, *pats, **opts)
960 return orig(ui, repo, *pats, **opts)
977
961
978 def overrideforget(orig, ui, repo, *pats, **opts):
962 def overrideforget(orig, ui, repo, *pats, **opts):
979 installnormalfilesmatchfn(repo[None].manifest())
963 installnormalfilesmatchfn(repo[None].manifest())
980 result = orig(ui, repo, *pats, **opts)
964 result = orig(ui, repo, *pats, **opts)
981 restorematchfn()
965 restorematchfn()
982 m = scmutil.match(repo[None], pats, opts)
966 m = scmutil.match(repo[None], pats, opts)
983
967
984 try:
968 try:
985 repo.lfstatus = True
969 repo.lfstatus = True
986 s = repo.status(match=m, clean=True)
970 s = repo.status(match=m, clean=True)
987 finally:
971 finally:
988 repo.lfstatus = False
972 repo.lfstatus = False
989 forget = sorted(s[0] + s[1] + s[3] + s[6])
973 forget = sorted(s[0] + s[1] + s[3] + s[6])
990 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
974 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
991
975
992 for f in forget:
976 for f in forget:
993 if lfutil.standin(f) not in repo.dirstate and not \
977 if lfutil.standin(f) not in repo.dirstate and not \
994 os.path.isdir(m.rel(lfutil.standin(f))):
978 os.path.isdir(m.rel(lfutil.standin(f))):
995 ui.warn(_('not removing %s: file is already untracked\n')
979 ui.warn(_('not removing %s: file is already untracked\n')
996 % m.rel(f))
980 % m.rel(f))
997 result = 1
981 result = 1
998
982
999 for f in forget:
983 for f in forget:
1000 if ui.verbose or not m.exact(f):
984 if ui.verbose or not m.exact(f):
1001 ui.status(_('removing %s\n') % m.rel(f))
985 ui.status(_('removing %s\n') % m.rel(f))
1002
986
1003 # Need to lock because standin files are deleted then removed from the
987 # Need to lock because standin files are deleted then removed from the
1004 # repository and we could race in-between.
988 # repository and we could race in-between.
1005 wlock = repo.wlock()
989 wlock = repo.wlock()
1006 try:
990 try:
1007 lfdirstate = lfutil.openlfdirstate(ui, repo)
991 lfdirstate = lfutil.openlfdirstate(ui, repo)
1008 for f in forget:
992 for f in forget:
1009 if lfdirstate[f] == 'a':
993 if lfdirstate[f] == 'a':
1010 lfdirstate.drop(f)
994 lfdirstate.drop(f)
1011 else:
995 else:
1012 lfdirstate.remove(f)
996 lfdirstate.remove(f)
1013 lfdirstate.write()
997 lfdirstate.write()
1014 standins = [lfutil.standin(f) for f in forget]
998 standins = [lfutil.standin(f) for f in forget]
1015 for f in standins:
999 for f in standins:
1016 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1000 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1017 repo[None].forget(standins)
1001 repo[None].forget(standins)
1018 finally:
1002 finally:
1019 wlock.release()
1003 wlock.release()
1020
1004
1021 return result
1005 return result
1022
1006
1023 def getoutgoinglfiles(ui, repo, dest=None, **opts):
1007 def getoutgoinglfiles(ui, repo, dest=None, **opts):
1024 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1008 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1025 dest, branches = hg.parseurl(dest, opts.get('branch'))
1009 dest, branches = hg.parseurl(dest, opts.get('branch'))
1026 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
1010 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
1027 if revs:
1011 if revs:
1028 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
1012 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
1029
1013
1030 try:
1014 try:
1031 remote = hg.peer(repo, opts, dest)
1015 remote = hg.peer(repo, opts, dest)
1032 except error.RepoError:
1016 except error.RepoError:
1033 return None
1017 return None
1034 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
1018 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
1035 if not outgoing.missing:
1019 if not outgoing.missing:
1036 return outgoing.missing
1020 return outgoing.missing
1037 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1021 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1038 if opts.get('newest_first'):
1022 if opts.get('newest_first'):
1039 o.reverse()
1023 o.reverse()
1040
1024
1041 toupload = set()
1025 toupload = set()
1042 for n in o:
1026 for n in o:
1043 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1027 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1044 ctx = repo[n]
1028 ctx = repo[n]
1045 files = set(ctx.files())
1029 files = set(ctx.files())
1046 if len(parents) == 2:
1030 if len(parents) == 2:
1047 mc = ctx.manifest()
1031 mc = ctx.manifest()
1048 mp1 = ctx.parents()[0].manifest()
1032 mp1 = ctx.parents()[0].manifest()
1049 mp2 = ctx.parents()[1].manifest()
1033 mp2 = ctx.parents()[1].manifest()
1050 for f in mp1:
1034 for f in mp1:
1051 if f not in mc:
1035 if f not in mc:
1052 files.add(f)
1036 files.add(f)
1053 for f in mp2:
1037 for f in mp2:
1054 if f not in mc:
1038 if f not in mc:
1055 files.add(f)
1039 files.add(f)
1056 for f in mc:
1040 for f in mc:
1057 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1041 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1058 files.add(f)
1042 files.add(f)
1059 toupload = toupload.union(
1043 toupload = toupload.union(
1060 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1044 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1061 return sorted(toupload)
1045 return sorted(toupload)
1062
1046
1063 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1047 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1064 result = orig(ui, repo, dest, **opts)
1048 result = orig(ui, repo, dest, **opts)
1065
1049
1066 if opts.pop('large', None):
1050 if opts.pop('large', None):
1067 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1051 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1068 if toupload is None:
1052 if toupload is None:
1069 ui.status(_('largefiles: No remote repo\n'))
1053 ui.status(_('largefiles: No remote repo\n'))
1070 elif not toupload:
1054 elif not toupload:
1071 ui.status(_('largefiles: no files to upload\n'))
1055 ui.status(_('largefiles: no files to upload\n'))
1072 else:
1056 else:
1073 ui.status(_('largefiles to upload:\n'))
1057 ui.status(_('largefiles to upload:\n'))
1074 for file in toupload:
1058 for file in toupload:
1075 ui.status(lfutil.splitstandin(file) + '\n')
1059 ui.status(lfutil.splitstandin(file) + '\n')
1076 ui.status('\n')
1060 ui.status('\n')
1077
1061
1078 return result
1062 return result
1079
1063
1080 def overridesummary(orig, ui, repo, *pats, **opts):
1064 def overridesummary(orig, ui, repo, *pats, **opts):
1081 try:
1065 try:
1082 repo.lfstatus = True
1066 repo.lfstatus = True
1083 orig(ui, repo, *pats, **opts)
1067 orig(ui, repo, *pats, **opts)
1084 finally:
1068 finally:
1085 repo.lfstatus = False
1069 repo.lfstatus = False
1086
1070
1087 if opts.pop('large', None):
1071 if opts.pop('large', None):
1088 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1072 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1089 if toupload is None:
1073 if toupload is None:
1090 # i18n: column positioning for "hg summary"
1074 # i18n: column positioning for "hg summary"
1091 ui.status(_('largefiles: (no remote repo)\n'))
1075 ui.status(_('largefiles: (no remote repo)\n'))
1092 elif not toupload:
1076 elif not toupload:
1093 # i18n: column positioning for "hg summary"
1077 # i18n: column positioning for "hg summary"
1094 ui.status(_('largefiles: (no files to upload)\n'))
1078 ui.status(_('largefiles: (no files to upload)\n'))
1095 else:
1079 else:
1096 # i18n: column positioning for "hg summary"
1080 # i18n: column positioning for "hg summary"
1097 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1081 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1098
1082
1099 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1083 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1100 similarity=None):
1084 similarity=None):
1101 if not lfutil.islfilesrepo(repo):
1085 if not lfutil.islfilesrepo(repo):
1102 return orig(repo, pats, opts, dry_run, similarity)
1086 return orig(repo, pats, opts, dry_run, similarity)
1103 # Get the list of missing largefiles so we can remove them
1087 # Get the list of missing largefiles so we can remove them
1104 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1088 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1105 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1089 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1106 False, False)
1090 False, False)
1107 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1091 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1108
1092
1109 # Call into the normal remove code, but the removing of the standin, we want
1093 # Call into the normal remove code, but the removing of the standin, we want
1110 # to have handled by original addremove. Monkey patching here makes sure
1094 # to have handled by original addremove. Monkey patching here makes sure
1111 # we don't remove the standin in the largefiles code, preventing a very
1095 # we don't remove the standin in the largefiles code, preventing a very
1112 # confused state later.
1096 # confused state later.
1113 if missing:
1097 if missing:
1114 m = [repo.wjoin(f) for f in missing]
1098 m = [repo.wjoin(f) for f in missing]
1115 repo._isaddremove = True
1099 repo._isaddremove = True
1116 removelargefiles(repo.ui, repo, *m, **opts)
1100 removelargefiles(repo.ui, repo, *m, **opts)
1117 repo._isaddremove = False
1101 repo._isaddremove = False
1118 # Call into the normal add code, and any files that *should* be added as
1102 # Call into the normal add code, and any files that *should* be added as
1119 # largefiles will be
1103 # largefiles will be
1120 addlargefiles(repo.ui, repo, *pats, **opts)
1104 addlargefiles(repo.ui, repo, *pats, **opts)
1121 # Now that we've handled largefiles, hand off to the original addremove
1105 # Now that we've handled largefiles, hand off to the original addremove
1122 # function to take care of the rest. Make sure it doesn't do anything with
1106 # function to take care of the rest. Make sure it doesn't do anything with
1123 # largefiles by installing a matcher that will ignore them.
1107 # largefiles by installing a matcher that will ignore them.
1124 installnormalfilesmatchfn(repo[None].manifest())
1108 installnormalfilesmatchfn(repo[None].manifest())
1125 result = orig(repo, pats, opts, dry_run, similarity)
1109 result = orig(repo, pats, opts, dry_run, similarity)
1126 restorematchfn()
1110 restorematchfn()
1127 return result
1111 return result
1128
1112
1129 # Calling purge with --all will cause the largefiles to be deleted.
1113 # Calling purge with --all will cause the largefiles to be deleted.
1130 # Override repo.status to prevent this from happening.
1114 # Override repo.status to prevent this from happening.
1131 def overridepurge(orig, ui, repo, *dirs, **opts):
1115 def overridepurge(orig, ui, repo, *dirs, **opts):
1132 # XXX large file status is buggy when used on repo proxy.
1116 # XXX large file status is buggy when used on repo proxy.
1133 # XXX this needs to be investigate.
1117 # XXX this needs to be investigate.
1134 repo = repo.unfiltered()
1118 repo = repo.unfiltered()
1135 oldstatus = repo.status
1119 oldstatus = repo.status
1136 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1120 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1137 clean=False, unknown=False, listsubrepos=False):
1121 clean=False, unknown=False, listsubrepos=False):
1138 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1122 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1139 listsubrepos)
1123 listsubrepos)
1140 lfdirstate = lfutil.openlfdirstate(ui, repo)
1124 lfdirstate = lfutil.openlfdirstate(ui, repo)
1141 modified, added, removed, deleted, unknown, ignored, clean = r
1125 modified, added, removed, deleted, unknown, ignored, clean = r
1142 unknown = [f for f in unknown if lfdirstate[f] == '?']
1126 unknown = [f for f in unknown if lfdirstate[f] == '?']
1143 ignored = [f for f in ignored if lfdirstate[f] == '?']
1127 ignored = [f for f in ignored if lfdirstate[f] == '?']
1144 return modified, added, removed, deleted, unknown, ignored, clean
1128 return modified, added, removed, deleted, unknown, ignored, clean
1145 repo.status = overridestatus
1129 repo.status = overridestatus
1146 orig(ui, repo, *dirs, **opts)
1130 orig(ui, repo, *dirs, **opts)
1147 repo.status = oldstatus
1131 repo.status = oldstatus
1148
1132
1149 def overriderollback(orig, ui, repo, **opts):
1133 def overriderollback(orig, ui, repo, **opts):
1150 result = orig(ui, repo, **opts)
1134 result = orig(ui, repo, **opts)
1151 merge.update(repo, node=None, branchmerge=False, force=True,
1135 merge.update(repo, node=None, branchmerge=False, force=True,
1152 partial=lfutil.isstandin)
1136 partial=lfutil.isstandin)
1153 wlock = repo.wlock()
1137 wlock = repo.wlock()
1154 try:
1138 try:
1155 lfdirstate = lfutil.openlfdirstate(ui, repo)
1139 lfdirstate = lfutil.openlfdirstate(ui, repo)
1156 lfiles = lfutil.listlfiles(repo)
1140 lfiles = lfutil.listlfiles(repo)
1157 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1141 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1158 for file in lfiles:
1142 for file in lfiles:
1159 if file in oldlfiles:
1143 if file in oldlfiles:
1160 lfdirstate.normallookup(file)
1144 lfdirstate.normallookup(file)
1161 else:
1145 else:
1162 lfdirstate.add(file)
1146 lfdirstate.add(file)
1163 lfdirstate.write()
1147 lfdirstate.write()
1164 finally:
1148 finally:
1165 wlock.release()
1149 wlock.release()
1166 return result
1150 return result
1167
1151
1168 def overridetransplant(orig, ui, repo, *revs, **opts):
1152 def overridetransplant(orig, ui, repo, *revs, **opts):
1169 try:
1153 try:
1170 oldstandins = lfutil.getstandinsstate(repo)
1154 oldstandins = lfutil.getstandinsstate(repo)
1171 repo._istransplanting = True
1155 repo._istransplanting = True
1172 result = orig(ui, repo, *revs, **opts)
1156 result = orig(ui, repo, *revs, **opts)
1173 newstandins = lfutil.getstandinsstate(repo)
1157 newstandins = lfutil.getstandinsstate(repo)
1174 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1158 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1175 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1159 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1176 printmessage=True)
1160 printmessage=True)
1177 finally:
1161 finally:
1178 repo._istransplanting = False
1162 repo._istransplanting = False
1179 return result
1163 return result
1180
1164
1181 def overridecat(orig, ui, repo, file1, *pats, **opts):
1165 def overridecat(orig, ui, repo, file1, *pats, **opts):
1182 ctx = scmutil.revsingle(repo, opts.get('rev'))
1166 ctx = scmutil.revsingle(repo, opts.get('rev'))
1183 err = 1
1167 err = 1
1184 notbad = set()
1168 notbad = set()
1185 m = scmutil.match(ctx, (file1,) + pats, opts)
1169 m = scmutil.match(ctx, (file1,) + pats, opts)
1186 origmatchfn = m.matchfn
1170 origmatchfn = m.matchfn
1187 def lfmatchfn(f):
1171 def lfmatchfn(f):
1188 lf = lfutil.splitstandin(f)
1172 lf = lfutil.splitstandin(f)
1189 if lf is None:
1173 if lf is None:
1190 return origmatchfn(f)
1174 return origmatchfn(f)
1191 notbad.add(lf)
1175 notbad.add(lf)
1192 return origmatchfn(lf)
1176 return origmatchfn(lf)
1193 m.matchfn = lfmatchfn
1177 m.matchfn = lfmatchfn
1194 origbadfn = m.bad
1178 origbadfn = m.bad
1195 def lfbadfn(f, msg):
1179 def lfbadfn(f, msg):
1196 if not f in notbad:
1180 if not f in notbad:
1197 return origbadfn(f, msg)
1181 return origbadfn(f, msg)
1198 m.bad = lfbadfn
1182 m.bad = lfbadfn
1199 for f in ctx.walk(m):
1183 for f in ctx.walk(m):
1200 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1184 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1201 pathname=f)
1185 pathname=f)
1202 lf = lfutil.splitstandin(f)
1186 lf = lfutil.splitstandin(f)
1203 if lf is None:
1187 if lf is None:
1204 # duplicating unreachable code from commands.cat
1188 # duplicating unreachable code from commands.cat
1205 data = ctx[f].data()
1189 data = ctx[f].data()
1206 if opts.get('decode'):
1190 if opts.get('decode'):
1207 data = repo.wwritedata(f, data)
1191 data = repo.wwritedata(f, data)
1208 fp.write(data)
1192 fp.write(data)
1209 else:
1193 else:
1210 hash = lfutil.readstandin(repo, lf, ctx.rev())
1194 hash = lfutil.readstandin(repo, lf, ctx.rev())
1211 if not lfutil.inusercache(repo.ui, hash):
1195 if not lfutil.inusercache(repo.ui, hash):
1212 store = basestore._openstore(repo)
1196 store = basestore._openstore(repo)
1213 success, missing = store.get([(lf, hash)])
1197 success, missing = store.get([(lf, hash)])
1214 if len(success) != 1:
1198 if len(success) != 1:
1215 raise util.Abort(
1199 raise util.Abort(
1216 _('largefile %s is not in cache and could not be '
1200 _('largefile %s is not in cache and could not be '
1217 'downloaded') % lf)
1201 'downloaded') % lf)
1218 path = lfutil.usercachepath(repo.ui, hash)
1202 path = lfutil.usercachepath(repo.ui, hash)
1219 fpin = open(path, "rb")
1203 fpin = open(path, "rb")
1220 for chunk in lfutil.blockstream(fpin):
1204 for chunk in lfutil.blockstream(fpin):
1221 fp.write(chunk)
1205 fp.write(chunk)
1222 fpin.close()
1206 fpin.close()
1223 fp.close()
1207 fp.close()
1224 err = 0
1208 err = 0
1225 return err
1209 return err
1226
1210
1227 def mercurialsinkbefore(orig, sink):
1211 def mercurialsinkbefore(orig, sink):
1228 sink.repo._isconverting = True
1212 sink.repo._isconverting = True
1229 orig(sink)
1213 orig(sink)
1230
1214
1231 def mercurialsinkafter(orig, sink):
1215 def mercurialsinkafter(orig, sink):
1232 sink.repo._isconverting = False
1216 sink.repo._isconverting = False
1233 orig(sink)
1217 orig(sink)
@@ -1,180 +1,178 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 '''setup for largefiles extension: uisetup'''
9 '''setup for largefiles extension: uisetup'''
10
10
11 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
11 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
12 httppeer, localrepo, merge, scmutil, sshpeer, wireproto, revset
12 httppeer, localrepo, merge, scmutil, sshpeer, wireproto, revset
13 from mercurial.i18n import _
13 from mercurial.i18n import _
14 from mercurial.hgweb import hgweb_mod, webcommands
14 from mercurial.hgweb import hgweb_mod, webcommands
15 from mercurial.subrepo import hgsubrepo
15 from mercurial.subrepo import hgsubrepo
16
16
17 import overrides
17 import overrides
18 import proto
18 import proto
19
19
20 def uisetup(ui):
20 def uisetup(ui):
21 # Disable auto-status for some commands which assume that all
21 # Disable auto-status for some commands which assume that all
22 # files in the result are under Mercurial's control
22 # files in the result are under Mercurial's control
23
23
24 entry = extensions.wrapcommand(commands.table, 'add',
24 entry = extensions.wrapcommand(commands.table, 'add',
25 overrides.overrideadd)
25 overrides.overrideadd)
26 addopt = [('', 'large', None, _('add as largefile')),
26 addopt = [('', 'large', None, _('add as largefile')),
27 ('', 'normal', None, _('add as normal file')),
27 ('', 'normal', None, _('add as normal file')),
28 ('', 'lfsize', '', _('add all files above this size '
28 ('', 'lfsize', '', _('add all files above this size '
29 '(in megabytes) as largefiles '
29 '(in megabytes) as largefiles '
30 '(default: 10)'))]
30 '(default: 10)'))]
31 entry[1].extend(addopt)
31 entry[1].extend(addopt)
32
32
33 # The scmutil function is called both by the (trivial) addremove command,
33 # The scmutil function is called both by the (trivial) addremove command,
34 # and in the process of handling commit -A (issue3542)
34 # and in the process of handling commit -A (issue3542)
35 entry = extensions.wrapfunction(scmutil, 'addremove',
35 entry = extensions.wrapfunction(scmutil, 'addremove',
36 overrides.scmutiladdremove)
36 overrides.scmutiladdremove)
37 entry = extensions.wrapcommand(commands.table, 'remove',
37 entry = extensions.wrapcommand(commands.table, 'remove',
38 overrides.overrideremove)
38 overrides.overrideremove)
39 entry = extensions.wrapcommand(commands.table, 'forget',
39 entry = extensions.wrapcommand(commands.table, 'forget',
40 overrides.overrideforget)
40 overrides.overrideforget)
41
41
42 # Subrepos call status function
42 # Subrepos call status function
43 entry = extensions.wrapcommand(commands.table, 'status',
43 entry = extensions.wrapcommand(commands.table, 'status',
44 overrides.overridestatus)
44 overrides.overridestatus)
45 entry = extensions.wrapfunction(hgsubrepo, 'status',
45 entry = extensions.wrapfunction(hgsubrepo, 'status',
46 overrides.overridestatusfn)
46 overrides.overridestatusfn)
47
47
48 entry = extensions.wrapcommand(commands.table, 'log',
48 entry = extensions.wrapcommand(commands.table, 'log',
49 overrides.overridelog)
49 overrides.overridelog)
50 entry = extensions.wrapcommand(commands.table, 'rollback',
50 entry = extensions.wrapcommand(commands.table, 'rollback',
51 overrides.overriderollback)
51 overrides.overriderollback)
52 entry = extensions.wrapcommand(commands.table, 'verify',
52 entry = extensions.wrapcommand(commands.table, 'verify',
53 overrides.overrideverify)
53 overrides.overrideverify)
54
54
55 verifyopt = [('', 'large', None,
55 verifyopt = [('', 'large', None,
56 _('verify that all largefiles in current revision exists')),
56 _('verify that all largefiles in current revision exists')),
57 ('', 'lfa', None,
57 ('', 'lfa', None,
58 _('verify largefiles in all revisions, not just current')),
58 _('verify largefiles in all revisions, not just current')),
59 ('', 'lfc', None,
59 ('', 'lfc', None,
60 _('verify local largefile contents, not just existence'))]
60 _('verify local largefile contents, not just existence'))]
61 entry[1].extend(verifyopt)
61 entry[1].extend(verifyopt)
62
62
63 entry = extensions.wrapcommand(commands.table, 'debugstate',
63 entry = extensions.wrapcommand(commands.table, 'debugstate',
64 overrides.overridedebugstate)
64 overrides.overridedebugstate)
65 debugstateopt = [('', 'large', None, _('display largefiles dirstate'))]
65 debugstateopt = [('', 'large', None, _('display largefiles dirstate'))]
66 entry[1].extend(debugstateopt)
66 entry[1].extend(debugstateopt)
67
67
68 entry = extensions.wrapcommand(commands.table, 'outgoing',
68 entry = extensions.wrapcommand(commands.table, 'outgoing',
69 overrides.overrideoutgoing)
69 overrides.overrideoutgoing)
70 outgoingopt = [('', 'large', None, _('display outgoing largefiles'))]
70 outgoingopt = [('', 'large', None, _('display outgoing largefiles'))]
71 entry[1].extend(outgoingopt)
71 entry[1].extend(outgoingopt)
72 entry = extensions.wrapcommand(commands.table, 'summary',
72 entry = extensions.wrapcommand(commands.table, 'summary',
73 overrides.overridesummary)
73 overrides.overridesummary)
74 summaryopt = [('', 'large', None, _('display outgoing largefiles'))]
74 summaryopt = [('', 'large', None, _('display outgoing largefiles'))]
75 entry[1].extend(summaryopt)
75 entry[1].extend(summaryopt)
76
76
77 entry = extensions.wrapcommand(commands.table, 'update',
77 entry = extensions.wrapcommand(commands.table, 'update',
78 overrides.overrideupdate)
78 overrides.overrideupdate)
79 entry = extensions.wrapcommand(commands.table, 'pull',
79 entry = extensions.wrapcommand(commands.table, 'pull',
80 overrides.overridepull)
80 overrides.overridepull)
81 pullopt = [('', 'all-largefiles', None,
81 pullopt = [('', 'all-largefiles', None,
82 _('download all pulled versions of largefiles')),
82 _('download all pulled versions of largefiles')),
83 ('', 'cache-largefiles', None,
84 _('caches new largefiles in all pulled heads')),
85 ('', 'lfrev', [],
83 ('', 'lfrev', [],
86 _('download largefiles for these revisions'), _('REV'))]
84 _('download largefiles for these revisions'), _('REV'))]
87 entry[1].extend(pullopt)
85 entry[1].extend(pullopt)
88 revset.symbols['pulled'] = overrides.pulledrevsetsymbol
86 revset.symbols['pulled'] = overrides.pulledrevsetsymbol
89
87
90 entry = extensions.wrapcommand(commands.table, 'clone',
88 entry = extensions.wrapcommand(commands.table, 'clone',
91 overrides.overrideclone)
89 overrides.overrideclone)
92 cloneopt = [('', 'all-largefiles', None,
90 cloneopt = [('', 'all-largefiles', None,
93 _('download all versions of all largefiles'))]
91 _('download all versions of all largefiles'))]
94 entry[1].extend(cloneopt)
92 entry[1].extend(cloneopt)
95 entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone)
93 entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone)
96
94
97 entry = extensions.wrapcommand(commands.table, 'cat',
95 entry = extensions.wrapcommand(commands.table, 'cat',
98 overrides.overridecat)
96 overrides.overridecat)
99 entry = extensions.wrapfunction(merge, '_checkunknownfile',
97 entry = extensions.wrapfunction(merge, '_checkunknownfile',
100 overrides.overridecheckunknownfile)
98 overrides.overridecheckunknownfile)
101 entry = extensions.wrapfunction(merge, 'manifestmerge',
99 entry = extensions.wrapfunction(merge, 'manifestmerge',
102 overrides.overridemanifestmerge)
100 overrides.overridemanifestmerge)
103 entry = extensions.wrapfunction(filemerge, 'filemerge',
101 entry = extensions.wrapfunction(filemerge, 'filemerge',
104 overrides.overridefilemerge)
102 overrides.overridefilemerge)
105 entry = extensions.wrapfunction(cmdutil, 'copy',
103 entry = extensions.wrapfunction(cmdutil, 'copy',
106 overrides.overridecopy)
104 overrides.overridecopy)
107
105
108 # Summary calls dirty on the subrepos
106 # Summary calls dirty on the subrepos
109 entry = extensions.wrapfunction(hgsubrepo, 'dirty',
107 entry = extensions.wrapfunction(hgsubrepo, 'dirty',
110 overrides.overridedirty)
108 overrides.overridedirty)
111
109
112 # Backout calls revert so we need to override both the command and the
110 # Backout calls revert so we need to override both the command and the
113 # function
111 # function
114 entry = extensions.wrapcommand(commands.table, 'revert',
112 entry = extensions.wrapcommand(commands.table, 'revert',
115 overrides.overriderevert)
113 overrides.overriderevert)
116 entry = extensions.wrapfunction(commands, 'revert',
114 entry = extensions.wrapfunction(commands, 'revert',
117 overrides.overriderevert)
115 overrides.overriderevert)
118
116
119 extensions.wrapfunction(hg, 'updaterepo', overrides.hgupdaterepo)
117 extensions.wrapfunction(hg, 'updaterepo', overrides.hgupdaterepo)
120 extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
118 extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
121
119
122 extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
120 extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
123 extensions.wrapfunction(hgsubrepo, 'archive', overrides.hgsubrepoarchive)
121 extensions.wrapfunction(hgsubrepo, 'archive', overrides.hgsubrepoarchive)
124 extensions.wrapfunction(cmdutil, 'bailifchanged',
122 extensions.wrapfunction(cmdutil, 'bailifchanged',
125 overrides.overridebailifchanged)
123 overrides.overridebailifchanged)
126
124
127 # create the new wireproto commands ...
125 # create the new wireproto commands ...
128 wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
126 wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
129 wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
127 wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
130 wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
128 wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
131
129
132 # ... and wrap some existing ones
130 # ... and wrap some existing ones
133 wireproto.commands['capabilities'] = (proto.capabilities, '')
131 wireproto.commands['capabilities'] = (proto.capabilities, '')
134 wireproto.commands['heads'] = (proto.heads, '')
132 wireproto.commands['heads'] = (proto.heads, '')
135 wireproto.commands['lheads'] = (wireproto.heads, '')
133 wireproto.commands['lheads'] = (wireproto.heads, '')
136
134
137 # make putlfile behave the same as push and {get,stat}lfile behave
135 # make putlfile behave the same as push and {get,stat}lfile behave
138 # the same as pull w.r.t. permissions checks
136 # the same as pull w.r.t. permissions checks
139 hgweb_mod.perms['putlfile'] = 'push'
137 hgweb_mod.perms['putlfile'] = 'push'
140 hgweb_mod.perms['getlfile'] = 'pull'
138 hgweb_mod.perms['getlfile'] = 'pull'
141 hgweb_mod.perms['statlfile'] = 'pull'
139 hgweb_mod.perms['statlfile'] = 'pull'
142
140
143 extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
141 extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
144
142
145 # the hello wireproto command uses wireproto.capabilities, so it won't see
143 # the hello wireproto command uses wireproto.capabilities, so it won't see
146 # our largefiles capability unless we replace the actual function as well.
144 # our largefiles capability unless we replace the actual function as well.
147 proto.capabilitiesorig = wireproto.capabilities
145 proto.capabilitiesorig = wireproto.capabilities
148 wireproto.capabilities = proto.capabilities
146 wireproto.capabilities = proto.capabilities
149
147
150 # can't do this in reposetup because it needs to have happened before
148 # can't do this in reposetup because it needs to have happened before
151 # wirerepo.__init__ is called
149 # wirerepo.__init__ is called
152 proto.ssholdcallstream = sshpeer.sshpeer._callstream
150 proto.ssholdcallstream = sshpeer.sshpeer._callstream
153 proto.httpoldcallstream = httppeer.httppeer._callstream
151 proto.httpoldcallstream = httppeer.httppeer._callstream
154 sshpeer.sshpeer._callstream = proto.sshrepocallstream
152 sshpeer.sshpeer._callstream = proto.sshrepocallstream
155 httppeer.httppeer._callstream = proto.httprepocallstream
153 httppeer.httppeer._callstream = proto.httprepocallstream
156
154
157 # don't die on seeing a repo with the largefiles requirement
155 # don't die on seeing a repo with the largefiles requirement
158 localrepo.localrepository.supported |= set(['largefiles'])
156 localrepo.localrepository.supported |= set(['largefiles'])
159
157
160 # override some extensions' stuff as well
158 # override some extensions' stuff as well
161 for name, module in extensions.extensions():
159 for name, module in extensions.extensions():
162 if name == 'fetch':
160 if name == 'fetch':
163 extensions.wrapcommand(getattr(module, 'cmdtable'), 'fetch',
161 extensions.wrapcommand(getattr(module, 'cmdtable'), 'fetch',
164 overrides.overridefetch)
162 overrides.overridefetch)
165 if name == 'purge':
163 if name == 'purge':
166 extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
164 extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
167 overrides.overridepurge)
165 overrides.overridepurge)
168 if name == 'rebase':
166 if name == 'rebase':
169 extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase',
167 extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase',
170 overrides.overriderebase)
168 overrides.overriderebase)
171 if name == 'transplant':
169 if name == 'transplant':
172 extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
170 extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
173 overrides.overridetransplant)
171 overrides.overridetransplant)
174 if name == 'convert':
172 if name == 'convert':
175 convcmd = getattr(module, 'convcmd')
173 convcmd = getattr(module, 'convcmd')
176 hgsink = getattr(convcmd, 'mercurial_sink')
174 hgsink = getattr(convcmd, 'mercurial_sink')
177 extensions.wrapfunction(hgsink, 'before',
175 extensions.wrapfunction(hgsink, 'before',
178 overrides.mercurialsinkbefore)
176 overrides.mercurialsinkbefore)
179 extensions.wrapfunction(hgsink, 'after',
177 extensions.wrapfunction(hgsink, 'after',
180 overrides.mercurialsinkafter)
178 overrides.mercurialsinkafter)
@@ -1,2218 +1,2217 b''
1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
2 $ mkdir "${USERCACHE}"
2 $ mkdir "${USERCACHE}"
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > largefiles=
5 > largefiles=
6 > purge=
6 > purge=
7 > rebase=
7 > rebase=
8 > transplant=
8 > transplant=
9 > [phases]
9 > [phases]
10 > publish=False
10 > publish=False
11 > [largefiles]
11 > [largefiles]
12 > minsize=2
12 > minsize=2
13 > patterns=glob:**.dat
13 > patterns=glob:**.dat
14 > usercache=${USERCACHE}
14 > usercache=${USERCACHE}
15 > [hooks]
15 > [hooks]
16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
17 > EOF
17 > EOF
18
18
19 Create the repo with a couple of revisions of both large and normal
19 Create the repo with a couple of revisions of both large and normal
20 files.
20 files.
21 Test status and dirstate of largefiles and that summary output is correct.
21 Test status and dirstate of largefiles and that summary output is correct.
22
22
23 $ hg init a
23 $ hg init a
24 $ cd a
24 $ cd a
25 $ mkdir sub
25 $ mkdir sub
26 $ echo normal1 > normal1
26 $ echo normal1 > normal1
27 $ echo normal2 > sub/normal2
27 $ echo normal2 > sub/normal2
28 $ echo large1 > large1
28 $ echo large1 > large1
29 $ echo large2 > sub/large2
29 $ echo large2 > sub/large2
30 $ hg add normal1 sub/normal2
30 $ hg add normal1 sub/normal2
31 $ hg add --large large1 sub/large2
31 $ hg add --large large1 sub/large2
32 $ hg commit -m "add files"
32 $ hg commit -m "add files"
33 Invoking status precommit hook
33 Invoking status precommit hook
34 A large1
34 A large1
35 A normal1
35 A normal1
36 A sub/large2
36 A sub/large2
37 A sub/normal2
37 A sub/normal2
38 $ touch large1 sub/large2
38 $ touch large1 sub/large2
39 $ sleep 1
39 $ sleep 1
40 $ hg st
40 $ hg st
41 $ hg debugstate --nodates
41 $ hg debugstate --nodates
42 n 644 41 .hglf/large1
42 n 644 41 .hglf/large1
43 n 644 41 .hglf/sub/large2
43 n 644 41 .hglf/sub/large2
44 n 644 8 normal1
44 n 644 8 normal1
45 n 644 8 sub/normal2
45 n 644 8 sub/normal2
46 $ hg debugstate --large
46 $ hg debugstate --large
47 n 644 7 large1
47 n 644 7 large1
48 n 644 7 sub/large2
48 n 644 7 sub/large2
49 $ echo normal11 > normal1
49 $ echo normal11 > normal1
50 $ echo normal22 > sub/normal2
50 $ echo normal22 > sub/normal2
51 $ echo large11 > large1
51 $ echo large11 > large1
52 $ echo large22 > sub/large2
52 $ echo large22 > sub/large2
53 $ hg commit -m "edit files"
53 $ hg commit -m "edit files"
54 Invoking status precommit hook
54 Invoking status precommit hook
55 M large1
55 M large1
56 M normal1
56 M normal1
57 M sub/large2
57 M sub/large2
58 M sub/normal2
58 M sub/normal2
59 $ hg sum --large
59 $ hg sum --large
60 parent: 1:ce8896473775 tip
60 parent: 1:ce8896473775 tip
61 edit files
61 edit files
62 branch: default
62 branch: default
63 commit: (clean)
63 commit: (clean)
64 update: (current)
64 update: (current)
65 largefiles: (no remote repo)
65 largefiles: (no remote repo)
66
66
67 Commit preserved largefile contents.
67 Commit preserved largefile contents.
68
68
69 $ cat normal1
69 $ cat normal1
70 normal11
70 normal11
71 $ cat large1
71 $ cat large1
72 large11
72 large11
73 $ cat sub/normal2
73 $ cat sub/normal2
74 normal22
74 normal22
75 $ cat sub/large2
75 $ cat sub/large2
76 large22
76 large22
77
77
78 Test status, subdir and unknown files
78 Test status, subdir and unknown files
79
79
80 $ echo unknown > sub/unknown
80 $ echo unknown > sub/unknown
81 $ hg st --all
81 $ hg st --all
82 ? sub/unknown
82 ? sub/unknown
83 C large1
83 C large1
84 C normal1
84 C normal1
85 C sub/large2
85 C sub/large2
86 C sub/normal2
86 C sub/normal2
87 $ hg st --all sub
87 $ hg st --all sub
88 ? sub/unknown
88 ? sub/unknown
89 C sub/large2
89 C sub/large2
90 C sub/normal2
90 C sub/normal2
91 $ rm sub/unknown
91 $ rm sub/unknown
92
92
93 Test messages and exit codes for remove warning cases
93 Test messages and exit codes for remove warning cases
94
94
95 $ hg remove -A large1
95 $ hg remove -A large1
96 not removing large1: file still exists
96 not removing large1: file still exists
97 [1]
97 [1]
98 $ echo 'modified' > large1
98 $ echo 'modified' > large1
99 $ hg remove large1
99 $ hg remove large1
100 not removing large1: file is modified (use -f to force removal)
100 not removing large1: file is modified (use -f to force removal)
101 [1]
101 [1]
102 $ echo 'new' > normalnew
102 $ echo 'new' > normalnew
103 $ hg add normalnew
103 $ hg add normalnew
104 $ echo 'new' > largenew
104 $ echo 'new' > largenew
105 $ hg add --large normalnew
105 $ hg add --large normalnew
106 normalnew already tracked!
106 normalnew already tracked!
107 $ hg remove normalnew largenew
107 $ hg remove normalnew largenew
108 not removing largenew: file is untracked
108 not removing largenew: file is untracked
109 not removing normalnew: file has been marked for add (use forget to undo)
109 not removing normalnew: file has been marked for add (use forget to undo)
110 [1]
110 [1]
111 $ rm normalnew largenew
111 $ rm normalnew largenew
112 $ hg up -Cq
112 $ hg up -Cq
113
113
114 Remove both largefiles and normal files.
114 Remove both largefiles and normal files.
115
115
116 $ hg remove normal1 large1
116 $ hg remove normal1 large1
117 $ hg status large1
117 $ hg status large1
118 R large1
118 R large1
119 $ hg commit -m "remove files"
119 $ hg commit -m "remove files"
120 Invoking status precommit hook
120 Invoking status precommit hook
121 R large1
121 R large1
122 R normal1
122 R normal1
123 $ ls
123 $ ls
124 sub
124 sub
125 $ echo "testlargefile" > large1-test
125 $ echo "testlargefile" > large1-test
126 $ hg add --large large1-test
126 $ hg add --large large1-test
127 $ hg st
127 $ hg st
128 A large1-test
128 A large1-test
129 $ hg rm large1-test
129 $ hg rm large1-test
130 not removing large1-test: file has been marked for add (use forget to undo)
130 not removing large1-test: file has been marked for add (use forget to undo)
131 [1]
131 [1]
132 $ hg st
132 $ hg st
133 A large1-test
133 A large1-test
134 $ hg forget large1-test
134 $ hg forget large1-test
135 $ hg st
135 $ hg st
136 ? large1-test
136 ? large1-test
137 $ hg remove large1-test
137 $ hg remove large1-test
138 not removing large1-test: file is untracked
138 not removing large1-test: file is untracked
139 [1]
139 [1]
140 $ hg forget large1-test
140 $ hg forget large1-test
141 not removing large1-test: file is already untracked
141 not removing large1-test: file is already untracked
142 [1]
142 [1]
143 $ rm large1-test
143 $ rm large1-test
144
144
145 Copy both largefiles and normal files (testing that status output is correct).
145 Copy both largefiles and normal files (testing that status output is correct).
146
146
147 $ hg cp sub/normal2 normal1
147 $ hg cp sub/normal2 normal1
148 $ hg cp sub/large2 large1
148 $ hg cp sub/large2 large1
149 $ hg commit -m "copy files"
149 $ hg commit -m "copy files"
150 Invoking status precommit hook
150 Invoking status precommit hook
151 A large1
151 A large1
152 A normal1
152 A normal1
153 $ cat normal1
153 $ cat normal1
154 normal22
154 normal22
155 $ cat large1
155 $ cat large1
156 large22
156 large22
157
157
158 Test moving largefiles and verify that normal files are also unaffected.
158 Test moving largefiles and verify that normal files are also unaffected.
159
159
160 $ hg mv normal1 normal3
160 $ hg mv normal1 normal3
161 $ hg mv large1 large3
161 $ hg mv large1 large3
162 $ hg mv sub/normal2 sub/normal4
162 $ hg mv sub/normal2 sub/normal4
163 $ hg mv sub/large2 sub/large4
163 $ hg mv sub/large2 sub/large4
164 $ hg commit -m "move files"
164 $ hg commit -m "move files"
165 Invoking status precommit hook
165 Invoking status precommit hook
166 A large3
166 A large3
167 A normal3
167 A normal3
168 A sub/large4
168 A sub/large4
169 A sub/normal4
169 A sub/normal4
170 R large1
170 R large1
171 R normal1
171 R normal1
172 R sub/large2
172 R sub/large2
173 R sub/normal2
173 R sub/normal2
174 $ cat normal3
174 $ cat normal3
175 normal22
175 normal22
176 $ cat large3
176 $ cat large3
177 large22
177 large22
178 $ cat sub/normal4
178 $ cat sub/normal4
179 normal22
179 normal22
180 $ cat sub/large4
180 $ cat sub/large4
181 large22
181 large22
182
182
183 Test repo method wrapping detection
183 Test repo method wrapping detection
184
184
185 $ cat > $TESTTMP/wrapping1.py <<EOF
185 $ cat > $TESTTMP/wrapping1.py <<EOF
186 > from hgext import largefiles
186 > from hgext import largefiles
187 > def reposetup(ui, repo):
187 > def reposetup(ui, repo):
188 > class derived(repo.__class__):
188 > class derived(repo.__class__):
189 > def push(self, *args, **kwargs):
189 > def push(self, *args, **kwargs):
190 > return super(derived, self).push(*args, **kwargs)
190 > return super(derived, self).push(*args, **kwargs)
191 > repo.__class__ = derived
191 > repo.__class__ = derived
192 > largefiles.reposetup(ui, repo)
192 > largefiles.reposetup(ui, repo)
193 > uisetup = largefiles.uisetup
193 > uisetup = largefiles.uisetup
194 > EOF
194 > EOF
195 $ hg --config extensions.largefiles=$TESTTMP/wrapping1.py status
195 $ hg --config extensions.largefiles=$TESTTMP/wrapping1.py status
196 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
196 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
197
197
198 $ cat > $TESTTMP/wrapping2.py <<EOF
198 $ cat > $TESTTMP/wrapping2.py <<EOF
199 > from hgext import largefiles
199 > from hgext import largefiles
200 > def reposetup(ui, repo):
200 > def reposetup(ui, repo):
201 > orgpush = repo.push
201 > orgpush = repo.push
202 > def push(*args, **kwargs):
202 > def push(*args, **kwargs):
203 > return orgpush(*args, **kwargs)
203 > return orgpush(*args, **kwargs)
204 > repo.push = push
204 > repo.push = push
205 > largefiles.reposetup(ui, repo)
205 > largefiles.reposetup(ui, repo)
206 > uisetup = largefiles.uisetup
206 > uisetup = largefiles.uisetup
207 > EOF
207 > EOF
208 $ hg --config extensions.largefiles=$TESTTMP/wrapping2.py status
208 $ hg --config extensions.largefiles=$TESTTMP/wrapping2.py status
209 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
209 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
210
210
211 Test copies and moves from a directory other than root (issue3516)
211 Test copies and moves from a directory other than root (issue3516)
212
212
213 $ cd ..
213 $ cd ..
214 $ hg init lf_cpmv
214 $ hg init lf_cpmv
215 $ cd lf_cpmv
215 $ cd lf_cpmv
216 $ mkdir dira
216 $ mkdir dira
217 $ mkdir dira/dirb
217 $ mkdir dira/dirb
218 $ touch dira/dirb/largefile
218 $ touch dira/dirb/largefile
219 $ hg add --large dira/dirb/largefile
219 $ hg add --large dira/dirb/largefile
220 $ hg commit -m "added"
220 $ hg commit -m "added"
221 Invoking status precommit hook
221 Invoking status precommit hook
222 A dira/dirb/largefile
222 A dira/dirb/largefile
223 $ cd dira
223 $ cd dira
224 $ hg cp dirb/largefile foo/largefile
224 $ hg cp dirb/largefile foo/largefile
225 $ hg ci -m "deep copy"
225 $ hg ci -m "deep copy"
226 Invoking status precommit hook
226 Invoking status precommit hook
227 A dira/foo/largefile
227 A dira/foo/largefile
228 $ find . | sort
228 $ find . | sort
229 .
229 .
230 ./dirb
230 ./dirb
231 ./dirb/largefile
231 ./dirb/largefile
232 ./foo
232 ./foo
233 ./foo/largefile
233 ./foo/largefile
234 $ hg mv foo/largefile baz/largefile
234 $ hg mv foo/largefile baz/largefile
235 $ hg ci -m "moved"
235 $ hg ci -m "moved"
236 Invoking status precommit hook
236 Invoking status precommit hook
237 A dira/baz/largefile
237 A dira/baz/largefile
238 R dira/foo/largefile
238 R dira/foo/largefile
239 $ find . | sort
239 $ find . | sort
240 .
240 .
241 ./baz
241 ./baz
242 ./baz/largefile
242 ./baz/largefile
243 ./dirb
243 ./dirb
244 ./dirb/largefile
244 ./dirb/largefile
245 ./foo
245 ./foo
246 $ cd ../../a
246 $ cd ../../a
247
247
248 #if serve
248 #if serve
249 Test display of largefiles in hgweb
249 Test display of largefiles in hgweb
250
250
251 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
251 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
252 $ cat ../hg.pid >> $DAEMON_PIDS
252 $ cat ../hg.pid >> $DAEMON_PIDS
253 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
253 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
254 200 Script output follows
254 200 Script output follows
255
255
256
256
257 drwxr-xr-x sub
257 drwxr-xr-x sub
258 -rw-r--r-- 41 large3
258 -rw-r--r-- 41 large3
259 -rw-r--r-- 9 normal3
259 -rw-r--r-- 9 normal3
260
260
261
261
262 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
262 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
263 200 Script output follows
263 200 Script output follows
264
264
265
265
266 -rw-r--r-- 41 large4
266 -rw-r--r-- 41 large4
267 -rw-r--r-- 9 normal4
267 -rw-r--r-- 9 normal4
268
268
269
269
270 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
270 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
271 #endif
271 #endif
272
272
273 Test archiving the various revisions. These hit corner cases known with
273 Test archiving the various revisions. These hit corner cases known with
274 archiving.
274 archiving.
275
275
276 $ hg archive -r 0 ../archive0
276 $ hg archive -r 0 ../archive0
277 $ hg archive -r 1 ../archive1
277 $ hg archive -r 1 ../archive1
278 $ hg archive -r 2 ../archive2
278 $ hg archive -r 2 ../archive2
279 $ hg archive -r 3 ../archive3
279 $ hg archive -r 3 ../archive3
280 $ hg archive -r 4 ../archive4
280 $ hg archive -r 4 ../archive4
281 $ cd ../archive0
281 $ cd ../archive0
282 $ cat normal1
282 $ cat normal1
283 normal1
283 normal1
284 $ cat large1
284 $ cat large1
285 large1
285 large1
286 $ cat sub/normal2
286 $ cat sub/normal2
287 normal2
287 normal2
288 $ cat sub/large2
288 $ cat sub/large2
289 large2
289 large2
290 $ cd ../archive1
290 $ cd ../archive1
291 $ cat normal1
291 $ cat normal1
292 normal11
292 normal11
293 $ cat large1
293 $ cat large1
294 large11
294 large11
295 $ cat sub/normal2
295 $ cat sub/normal2
296 normal22
296 normal22
297 $ cat sub/large2
297 $ cat sub/large2
298 large22
298 large22
299 $ cd ../archive2
299 $ cd ../archive2
300 $ ls
300 $ ls
301 sub
301 sub
302 $ cat sub/normal2
302 $ cat sub/normal2
303 normal22
303 normal22
304 $ cat sub/large2
304 $ cat sub/large2
305 large22
305 large22
306 $ cd ../archive3
306 $ cd ../archive3
307 $ cat normal1
307 $ cat normal1
308 normal22
308 normal22
309 $ cat large1
309 $ cat large1
310 large22
310 large22
311 $ cat sub/normal2
311 $ cat sub/normal2
312 normal22
312 normal22
313 $ cat sub/large2
313 $ cat sub/large2
314 large22
314 large22
315 $ cd ../archive4
315 $ cd ../archive4
316 $ cat normal3
316 $ cat normal3
317 normal22
317 normal22
318 $ cat large3
318 $ cat large3
319 large22
319 large22
320 $ cat sub/normal4
320 $ cat sub/normal4
321 normal22
321 normal22
322 $ cat sub/large4
322 $ cat sub/large4
323 large22
323 large22
324
324
325 Commit corner case: specify files to commit.
325 Commit corner case: specify files to commit.
326
326
327 $ cd ../a
327 $ cd ../a
328 $ echo normal3 > normal3
328 $ echo normal3 > normal3
329 $ echo large3 > large3
329 $ echo large3 > large3
330 $ echo normal4 > sub/normal4
330 $ echo normal4 > sub/normal4
331 $ echo large4 > sub/large4
331 $ echo large4 > sub/large4
332 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
332 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
333 Invoking status precommit hook
333 Invoking status precommit hook
334 M large3
334 M large3
335 M normal3
335 M normal3
336 M sub/large4
336 M sub/large4
337 M sub/normal4
337 M sub/normal4
338 $ cat normal3
338 $ cat normal3
339 normal3
339 normal3
340 $ cat large3
340 $ cat large3
341 large3
341 large3
342 $ cat sub/normal4
342 $ cat sub/normal4
343 normal4
343 normal4
344 $ cat sub/large4
344 $ cat sub/large4
345 large4
345 large4
346
346
347 One more commit corner case: commit from a subdirectory.
347 One more commit corner case: commit from a subdirectory.
348
348
349 $ cd ../a
349 $ cd ../a
350 $ echo normal33 > normal3
350 $ echo normal33 > normal3
351 $ echo large33 > large3
351 $ echo large33 > large3
352 $ echo normal44 > sub/normal4
352 $ echo normal44 > sub/normal4
353 $ echo large44 > sub/large4
353 $ echo large44 > sub/large4
354 $ cd sub
354 $ cd sub
355 $ hg commit -m "edit files yet again"
355 $ hg commit -m "edit files yet again"
356 Invoking status precommit hook
356 Invoking status precommit hook
357 M large3
357 M large3
358 M normal3
358 M normal3
359 M sub/large4
359 M sub/large4
360 M sub/normal4
360 M sub/normal4
361 $ cat ../normal3
361 $ cat ../normal3
362 normal33
362 normal33
363 $ cat ../large3
363 $ cat ../large3
364 large33
364 large33
365 $ cat normal4
365 $ cat normal4
366 normal44
366 normal44
367 $ cat large4
367 $ cat large4
368 large44
368 large44
369
369
370 Committing standins is not allowed.
370 Committing standins is not allowed.
371
371
372 $ cd ..
372 $ cd ..
373 $ echo large3 > large3
373 $ echo large3 > large3
374 $ hg commit .hglf/large3 -m "try to commit standin"
374 $ hg commit .hglf/large3 -m "try to commit standin"
375 abort: file ".hglf/large3" is a largefile standin
375 abort: file ".hglf/large3" is a largefile standin
376 (commit the largefile itself instead)
376 (commit the largefile itself instead)
377 [255]
377 [255]
378
378
379 Corner cases for adding largefiles.
379 Corner cases for adding largefiles.
380
380
381 $ echo large5 > large5
381 $ echo large5 > large5
382 $ hg add --large large5
382 $ hg add --large large5
383 $ hg add --large large5
383 $ hg add --large large5
384 large5 already a largefile
384 large5 already a largefile
385 $ mkdir sub2
385 $ mkdir sub2
386 $ echo large6 > sub2/large6
386 $ echo large6 > sub2/large6
387 $ echo large7 > sub2/large7
387 $ echo large7 > sub2/large7
388 $ hg add --large sub2
388 $ hg add --large sub2
389 adding sub2/large6 as a largefile (glob)
389 adding sub2/large6 as a largefile (glob)
390 adding sub2/large7 as a largefile (glob)
390 adding sub2/large7 as a largefile (glob)
391 $ hg st
391 $ hg st
392 M large3
392 M large3
393 A large5
393 A large5
394 A sub2/large6
394 A sub2/large6
395 A sub2/large7
395 A sub2/large7
396
396
397 Committing directories containing only largefiles.
397 Committing directories containing only largefiles.
398
398
399 $ mkdir -p z/y/x/m
399 $ mkdir -p z/y/x/m
400 $ touch z/y/x/m/large1
400 $ touch z/y/x/m/large1
401 $ touch z/y/x/large2
401 $ touch z/y/x/large2
402 $ hg add --large z/y/x/m/large1 z/y/x/large2
402 $ hg add --large z/y/x/m/large1 z/y/x/large2
403 $ hg commit -m "Subdir with directory only containing largefiles" z
403 $ hg commit -m "Subdir with directory only containing largefiles" z
404 Invoking status precommit hook
404 Invoking status precommit hook
405 M large3
405 M large3
406 A large5
406 A large5
407 A sub2/large6
407 A sub2/large6
408 A sub2/large7
408 A sub2/large7
409 A z/y/x/large2
409 A z/y/x/large2
410 A z/y/x/m/large1
410 A z/y/x/m/large1
411 $ hg rollback --quiet
411 $ hg rollback --quiet
412 $ touch z/y/x/m/normal
412 $ touch z/y/x/m/normal
413 $ hg add z/y/x/m/normal
413 $ hg add z/y/x/m/normal
414 $ hg commit -m "Subdir with mixed contents" z
414 $ hg commit -m "Subdir with mixed contents" z
415 Invoking status precommit hook
415 Invoking status precommit hook
416 M large3
416 M large3
417 A large5
417 A large5
418 A sub2/large6
418 A sub2/large6
419 A sub2/large7
419 A sub2/large7
420 A z/y/x/large2
420 A z/y/x/large2
421 A z/y/x/m/large1
421 A z/y/x/m/large1
422 A z/y/x/m/normal
422 A z/y/x/m/normal
423 $ hg st
423 $ hg st
424 M large3
424 M large3
425 A large5
425 A large5
426 A sub2/large6
426 A sub2/large6
427 A sub2/large7
427 A sub2/large7
428 $ hg rollback --quiet
428 $ hg rollback --quiet
429 $ hg revert z/y/x/large2 z/y/x/m/large1
429 $ hg revert z/y/x/large2 z/y/x/m/large1
430 $ rm z/y/x/large2 z/y/x/m/large1
430 $ rm z/y/x/large2 z/y/x/m/large1
431 $ hg commit -m "Subdir with normal contents" z
431 $ hg commit -m "Subdir with normal contents" z
432 Invoking status precommit hook
432 Invoking status precommit hook
433 M large3
433 M large3
434 A large5
434 A large5
435 A sub2/large6
435 A sub2/large6
436 A sub2/large7
436 A sub2/large7
437 A z/y/x/m/normal
437 A z/y/x/m/normal
438 $ hg st
438 $ hg st
439 M large3
439 M large3
440 A large5
440 A large5
441 A sub2/large6
441 A sub2/large6
442 A sub2/large7
442 A sub2/large7
443 $ hg rollback --quiet
443 $ hg rollback --quiet
444 $ hg revert --quiet z
444 $ hg revert --quiet z
445 $ hg commit -m "Empty subdir" z
445 $ hg commit -m "Empty subdir" z
446 abort: z: no match under directory!
446 abort: z: no match under directory!
447 [255]
447 [255]
448 $ rm -rf z
448 $ rm -rf z
449 $ hg ci -m "standin" .hglf
449 $ hg ci -m "standin" .hglf
450 abort: file ".hglf" is a largefile standin
450 abort: file ".hglf" is a largefile standin
451 (commit the largefile itself instead)
451 (commit the largefile itself instead)
452 [255]
452 [255]
453
453
454 Test "hg status" with combination of 'file pattern' and 'directory
454 Test "hg status" with combination of 'file pattern' and 'directory
455 pattern' for largefiles:
455 pattern' for largefiles:
456
456
457 $ hg status sub2/large6 sub2
457 $ hg status sub2/large6 sub2
458 A sub2/large6
458 A sub2/large6
459 A sub2/large7
459 A sub2/large7
460
460
461 Config settings (pattern **.dat, minsize 2 MB) are respected.
461 Config settings (pattern **.dat, minsize 2 MB) are respected.
462
462
463 $ echo testdata > test.dat
463 $ echo testdata > test.dat
464 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
464 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
465 $ hg add
465 $ hg add
466 adding reallylarge as a largefile
466 adding reallylarge as a largefile
467 adding test.dat as a largefile
467 adding test.dat as a largefile
468
468
469 Test that minsize and --lfsize handle float values;
469 Test that minsize and --lfsize handle float values;
470 also tests that --lfsize overrides largefiles.minsize.
470 also tests that --lfsize overrides largefiles.minsize.
471 (0.250 MB = 256 kB = 262144 B)
471 (0.250 MB = 256 kB = 262144 B)
472
472
473 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
473 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
474 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
474 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
475 $ hg --config largefiles.minsize=.25 add
475 $ hg --config largefiles.minsize=.25 add
476 adding ratherlarge as a largefile
476 adding ratherlarge as a largefile
477 adding medium
477 adding medium
478 $ hg forget medium
478 $ hg forget medium
479 $ hg --config largefiles.minsize=.25 add --lfsize=.125
479 $ hg --config largefiles.minsize=.25 add --lfsize=.125
480 adding medium as a largefile
480 adding medium as a largefile
481 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
481 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
482 $ hg --config largefiles.minsize=.25 add --lfsize=.125
482 $ hg --config largefiles.minsize=.25 add --lfsize=.125
483 adding notlarge
483 adding notlarge
484 $ hg forget notlarge
484 $ hg forget notlarge
485
485
486 Test forget on largefiles.
486 Test forget on largefiles.
487
487
488 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
488 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
489 $ hg commit -m "add/edit more largefiles"
489 $ hg commit -m "add/edit more largefiles"
490 Invoking status precommit hook
490 Invoking status precommit hook
491 A sub2/large6
491 A sub2/large6
492 A sub2/large7
492 A sub2/large7
493 R large3
493 R large3
494 ? large5
494 ? large5
495 ? medium
495 ? medium
496 ? notlarge
496 ? notlarge
497 ? ratherlarge
497 ? ratherlarge
498 ? reallylarge
498 ? reallylarge
499 ? test.dat
499 ? test.dat
500 $ hg st
500 $ hg st
501 ? large3
501 ? large3
502 ? large5
502 ? large5
503 ? medium
503 ? medium
504 ? notlarge
504 ? notlarge
505 ? ratherlarge
505 ? ratherlarge
506 ? reallylarge
506 ? reallylarge
507 ? test.dat
507 ? test.dat
508
508
509 Purge with largefiles: verify that largefiles are still in the working
509 Purge with largefiles: verify that largefiles are still in the working
510 dir after a purge.
510 dir after a purge.
511
511
512 $ hg purge --all
512 $ hg purge --all
513 $ cat sub/large4
513 $ cat sub/large4
514 large44
514 large44
515 $ cat sub2/large6
515 $ cat sub2/large6
516 large6
516 large6
517 $ cat sub2/large7
517 $ cat sub2/large7
518 large7
518 large7
519
519
520 Test addremove: verify that files that should be added as largfiles are added as
520 Test addremove: verify that files that should be added as largfiles are added as
521 such and that already-existing largfiles are not added as normal files by
521 such and that already-existing largfiles are not added as normal files by
522 accident.
522 accident.
523
523
524 $ rm normal3
524 $ rm normal3
525 $ rm sub/large4
525 $ rm sub/large4
526 $ echo "testing addremove with patterns" > testaddremove.dat
526 $ echo "testing addremove with patterns" > testaddremove.dat
527 $ echo "normaladdremove" > normaladdremove
527 $ echo "normaladdremove" > normaladdremove
528 $ hg addremove
528 $ hg addremove
529 removing sub/large4
529 removing sub/large4
530 adding testaddremove.dat as a largefile
530 adding testaddremove.dat as a largefile
531 removing normal3
531 removing normal3
532 adding normaladdremove
532 adding normaladdremove
533
533
534 Test addremove with -R
534 Test addremove with -R
535
535
536 $ hg up -C
536 $ hg up -C
537 getting changed largefiles
537 getting changed largefiles
538 1 largefiles updated, 0 removed
538 1 largefiles updated, 0 removed
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
540 $ rm normal3
540 $ rm normal3
541 $ rm sub/large4
541 $ rm sub/large4
542 $ echo "testing addremove with patterns" > testaddremove.dat
542 $ echo "testing addremove with patterns" > testaddremove.dat
543 $ echo "normaladdremove" > normaladdremove
543 $ echo "normaladdremove" > normaladdremove
544 $ cd ..
544 $ cd ..
545 $ hg -R a addremove
545 $ hg -R a addremove
546 removing sub/large4
546 removing sub/large4
547 adding a/testaddremove.dat as a largefile (glob)
547 adding a/testaddremove.dat as a largefile (glob)
548 removing normal3
548 removing normal3
549 adding normaladdremove
549 adding normaladdremove
550 $ cd a
550 $ cd a
551
551
552 Test 3364
552 Test 3364
553 $ hg clone . ../addrm
553 $ hg clone . ../addrm
554 updating to branch default
554 updating to branch default
555 getting changed largefiles
555 getting changed largefiles
556 3 largefiles updated, 0 removed
556 3 largefiles updated, 0 removed
557 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 $ cd ../addrm
558 $ cd ../addrm
559 $ cat >> .hg/hgrc <<EOF
559 $ cat >> .hg/hgrc <<EOF
560 > [hooks]
560 > [hooks]
561 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
561 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
562 > EOF
562 > EOF
563 $ touch foo
563 $ touch foo
564 $ hg add --large foo
564 $ hg add --large foo
565 $ hg ci -m "add foo"
565 $ hg ci -m "add foo"
566 Invoking status precommit hook
566 Invoking status precommit hook
567 A foo
567 A foo
568 Invoking status postcommit hook
568 Invoking status postcommit hook
569 C foo
569 C foo
570 C normal3
570 C normal3
571 C sub/large4
571 C sub/large4
572 C sub/normal4
572 C sub/normal4
573 C sub2/large6
573 C sub2/large6
574 C sub2/large7
574 C sub2/large7
575 $ rm foo
575 $ rm foo
576 $ hg st
576 $ hg st
577 ! foo
577 ! foo
578 hmm.. no precommit invoked, but there is a postcommit??
578 hmm.. no precommit invoked, but there is a postcommit??
579 $ hg ci -m "will not checkin"
579 $ hg ci -m "will not checkin"
580 nothing changed
580 nothing changed
581 Invoking status postcommit hook
581 Invoking status postcommit hook
582 ! foo
582 ! foo
583 C normal3
583 C normal3
584 C sub/large4
584 C sub/large4
585 C sub/normal4
585 C sub/normal4
586 C sub2/large6
586 C sub2/large6
587 C sub2/large7
587 C sub2/large7
588 [1]
588 [1]
589 $ hg addremove
589 $ hg addremove
590 removing foo
590 removing foo
591 $ hg st
591 $ hg st
592 R foo
592 R foo
593 $ hg ci -m "used to say nothing changed"
593 $ hg ci -m "used to say nothing changed"
594 Invoking status precommit hook
594 Invoking status precommit hook
595 R foo
595 R foo
596 Invoking status postcommit hook
596 Invoking status postcommit hook
597 C normal3
597 C normal3
598 C sub/large4
598 C sub/large4
599 C sub/normal4
599 C sub/normal4
600 C sub2/large6
600 C sub2/large6
601 C sub2/large7
601 C sub2/large7
602 $ hg st
602 $ hg st
603
603
604 Test 3507 (both normal files and largefiles were a problem)
604 Test 3507 (both normal files and largefiles were a problem)
605
605
606 $ touch normal
606 $ touch normal
607 $ touch large
607 $ touch large
608 $ hg add normal
608 $ hg add normal
609 $ hg add --large large
609 $ hg add --large large
610 $ hg ci -m "added"
610 $ hg ci -m "added"
611 Invoking status precommit hook
611 Invoking status precommit hook
612 A large
612 A large
613 A normal
613 A normal
614 Invoking status postcommit hook
614 Invoking status postcommit hook
615 C large
615 C large
616 C normal
616 C normal
617 C normal3
617 C normal3
618 C sub/large4
618 C sub/large4
619 C sub/normal4
619 C sub/normal4
620 C sub2/large6
620 C sub2/large6
621 C sub2/large7
621 C sub2/large7
622 $ hg remove normal
622 $ hg remove normal
623 $ hg addremove --traceback
623 $ hg addremove --traceback
624 $ hg ci -m "addremoved normal"
624 $ hg ci -m "addremoved normal"
625 Invoking status precommit hook
625 Invoking status precommit hook
626 R normal
626 R normal
627 Invoking status postcommit hook
627 Invoking status postcommit hook
628 C large
628 C large
629 C normal3
629 C normal3
630 C sub/large4
630 C sub/large4
631 C sub/normal4
631 C sub/normal4
632 C sub2/large6
632 C sub2/large6
633 C sub2/large7
633 C sub2/large7
634 $ hg up -C '.^'
634 $ hg up -C '.^'
635 getting changed largefiles
635 getting changed largefiles
636 0 largefiles updated, 0 removed
636 0 largefiles updated, 0 removed
637 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
637 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
638 $ hg remove large
638 $ hg remove large
639 $ hg addremove --traceback
639 $ hg addremove --traceback
640 $ hg ci -m "removed large"
640 $ hg ci -m "removed large"
641 Invoking status precommit hook
641 Invoking status precommit hook
642 R large
642 R large
643 created new head
643 created new head
644 Invoking status postcommit hook
644 Invoking status postcommit hook
645 C normal
645 C normal
646 C normal3
646 C normal3
647 C sub/large4
647 C sub/large4
648 C sub/normal4
648 C sub/normal4
649 C sub2/large6
649 C sub2/large6
650 C sub2/large7
650 C sub2/large7
651
651
652 Test commit -A (issue 3542)
652 Test commit -A (issue 3542)
653 $ echo large8 > large8
653 $ echo large8 > large8
654 $ hg add --large large8
654 $ hg add --large large8
655 $ hg ci -Am 'this used to add large8 as normal and commit both'
655 $ hg ci -Am 'this used to add large8 as normal and commit both'
656 Invoking status precommit hook
656 Invoking status precommit hook
657 A large8
657 A large8
658 Invoking status postcommit hook
658 Invoking status postcommit hook
659 C large8
659 C large8
660 C normal
660 C normal
661 C normal3
661 C normal3
662 C sub/large4
662 C sub/large4
663 C sub/normal4
663 C sub/normal4
664 C sub2/large6
664 C sub2/large6
665 C sub2/large7
665 C sub2/large7
666 $ rm large8
666 $ rm large8
667 $ hg ci -Am 'this used to not notice the rm'
667 $ hg ci -Am 'this used to not notice the rm'
668 removing large8
668 removing large8
669 Invoking status precommit hook
669 Invoking status precommit hook
670 R large8
670 R large8
671 Invoking status postcommit hook
671 Invoking status postcommit hook
672 C normal
672 C normal
673 C normal3
673 C normal3
674 C sub/large4
674 C sub/large4
675 C sub/normal4
675 C sub/normal4
676 C sub2/large6
676 C sub2/large6
677 C sub2/large7
677 C sub2/large7
678
678
679 Test that a standin can't be added as a large file
679 Test that a standin can't be added as a large file
680
680
681 $ touch large
681 $ touch large
682 $ hg add --large large
682 $ hg add --large large
683 $ hg ci -m "add"
683 $ hg ci -m "add"
684 Invoking status precommit hook
684 Invoking status precommit hook
685 A large
685 A large
686 Invoking status postcommit hook
686 Invoking status postcommit hook
687 C large
687 C large
688 C normal
688 C normal
689 C normal3
689 C normal3
690 C sub/large4
690 C sub/large4
691 C sub/normal4
691 C sub/normal4
692 C sub2/large6
692 C sub2/large6
693 C sub2/large7
693 C sub2/large7
694 $ hg remove large
694 $ hg remove large
695 $ touch large
695 $ touch large
696 $ hg addremove --config largefiles.patterns=**large --traceback
696 $ hg addremove --config largefiles.patterns=**large --traceback
697 adding large as a largefile
697 adding large as a largefile
698
698
699 Test that outgoing --large works (with revsets too)
699 Test that outgoing --large works (with revsets too)
700 $ hg outgoing --rev '.^' --large
700 $ hg outgoing --rev '.^' --large
701 comparing with $TESTTMP/a (glob)
701 comparing with $TESTTMP/a (glob)
702 searching for changes
702 searching for changes
703 changeset: 8:c02fd3b77ec4
703 changeset: 8:c02fd3b77ec4
704 user: test
704 user: test
705 date: Thu Jan 01 00:00:00 1970 +0000
705 date: Thu Jan 01 00:00:00 1970 +0000
706 summary: add foo
706 summary: add foo
707
707
708 changeset: 9:289dd08c9bbb
708 changeset: 9:289dd08c9bbb
709 user: test
709 user: test
710 date: Thu Jan 01 00:00:00 1970 +0000
710 date: Thu Jan 01 00:00:00 1970 +0000
711 summary: used to say nothing changed
711 summary: used to say nothing changed
712
712
713 changeset: 10:34f23ac6ac12
713 changeset: 10:34f23ac6ac12
714 user: test
714 user: test
715 date: Thu Jan 01 00:00:00 1970 +0000
715 date: Thu Jan 01 00:00:00 1970 +0000
716 summary: added
716 summary: added
717
717
718 changeset: 12:710c1b2f523c
718 changeset: 12:710c1b2f523c
719 parent: 10:34f23ac6ac12
719 parent: 10:34f23ac6ac12
720 user: test
720 user: test
721 date: Thu Jan 01 00:00:00 1970 +0000
721 date: Thu Jan 01 00:00:00 1970 +0000
722 summary: removed large
722 summary: removed large
723
723
724 changeset: 13:0a3e75774479
724 changeset: 13:0a3e75774479
725 user: test
725 user: test
726 date: Thu Jan 01 00:00:00 1970 +0000
726 date: Thu Jan 01 00:00:00 1970 +0000
727 summary: this used to add large8 as normal and commit both
727 summary: this used to add large8 as normal and commit both
728
728
729 changeset: 14:84f3d378175c
729 changeset: 14:84f3d378175c
730 user: test
730 user: test
731 date: Thu Jan 01 00:00:00 1970 +0000
731 date: Thu Jan 01 00:00:00 1970 +0000
732 summary: this used to not notice the rm
732 summary: this used to not notice the rm
733
733
734 searching for changes
734 searching for changes
735 largefiles to upload:
735 largefiles to upload:
736 foo
736 foo
737 large
737 large
738 large8
738 large8
739
739
740 $ cd ../a
740 $ cd ../a
741
741
742 Clone a largefiles repo.
742 Clone a largefiles repo.
743
743
744 $ hg clone . ../b
744 $ hg clone . ../b
745 updating to branch default
745 updating to branch default
746 getting changed largefiles
746 getting changed largefiles
747 3 largefiles updated, 0 removed
747 3 largefiles updated, 0 removed
748 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
748 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
749 $ cd ../b
749 $ cd ../b
750 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
750 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
751 7:daea875e9014 add/edit more largefiles
751 7:daea875e9014 add/edit more largefiles
752 6:4355d653f84f edit files yet again
752 6:4355d653f84f edit files yet again
753 5:9d5af5072dbd edit files again
753 5:9d5af5072dbd edit files again
754 4:74c02385b94c move files
754 4:74c02385b94c move files
755 3:9e8fbc4bce62 copy files
755 3:9e8fbc4bce62 copy files
756 2:51a0ae4d5864 remove files
756 2:51a0ae4d5864 remove files
757 1:ce8896473775 edit files
757 1:ce8896473775 edit files
758 0:30d30fe6a5be add files
758 0:30d30fe6a5be add files
759 $ cat normal3
759 $ cat normal3
760 normal33
760 normal33
761 $ cat sub/normal4
761 $ cat sub/normal4
762 normal44
762 normal44
763 $ cat sub/large4
763 $ cat sub/large4
764 large44
764 large44
765 $ cat sub2/large6
765 $ cat sub2/large6
766 large6
766 large6
767 $ cat sub2/large7
767 $ cat sub2/large7
768 large7
768 large7
769 $ cd ..
769 $ cd ..
770 $ hg clone a -r 3 c
770 $ hg clone a -r 3 c
771 adding changesets
771 adding changesets
772 adding manifests
772 adding manifests
773 adding file changes
773 adding file changes
774 added 4 changesets with 10 changes to 4 files
774 added 4 changesets with 10 changes to 4 files
775 updating to branch default
775 updating to branch default
776 getting changed largefiles
776 getting changed largefiles
777 2 largefiles updated, 0 removed
777 2 largefiles updated, 0 removed
778 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
778 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
779 $ cd c
779 $ cd c
780 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
780 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
781 3:9e8fbc4bce62 copy files
781 3:9e8fbc4bce62 copy files
782 2:51a0ae4d5864 remove files
782 2:51a0ae4d5864 remove files
783 1:ce8896473775 edit files
783 1:ce8896473775 edit files
784 0:30d30fe6a5be add files
784 0:30d30fe6a5be add files
785 $ cat normal1
785 $ cat normal1
786 normal22
786 normal22
787 $ cat large1
787 $ cat large1
788 large22
788 large22
789 $ cat sub/normal2
789 $ cat sub/normal2
790 normal22
790 normal22
791 $ cat sub/large2
791 $ cat sub/large2
792 large22
792 large22
793
793
794 Old revisions of a clone have correct largefiles content (this also
794 Old revisions of a clone have correct largefiles content (this also
795 tests update).
795 tests update).
796
796
797 $ hg update -r 1
797 $ hg update -r 1
798 getting changed largefiles
798 getting changed largefiles
799 1 largefiles updated, 0 removed
799 1 largefiles updated, 0 removed
800 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
800 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
801 $ cat large1
801 $ cat large1
802 large11
802 large11
803 $ cat sub/large2
803 $ cat sub/large2
804 large22
804 large22
805 $ cd ..
805 $ cd ..
806
806
807 Test cloning with --all-largefiles flag
807 Test cloning with --all-largefiles flag
808
808
809 $ rm "${USERCACHE}"/*
809 $ rm "${USERCACHE}"/*
810 $ hg clone --all-largefiles a a-backup
810 $ hg clone --all-largefiles a a-backup
811 updating to branch default
811 updating to branch default
812 getting changed largefiles
812 getting changed largefiles
813 3 largefiles updated, 0 removed
813 3 largefiles updated, 0 removed
814 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
814 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
815 8 additional largefiles cached
815 8 additional largefiles cached
816
816
817 $ rm "${USERCACHE}"/*
817 $ rm "${USERCACHE}"/*
818 $ hg clone --all-largefiles -u 0 a a-clone0
818 $ hg clone --all-largefiles -u 0 a a-clone0
819 updating to branch default
819 updating to branch default
820 getting changed largefiles
820 getting changed largefiles
821 2 largefiles updated, 0 removed
821 2 largefiles updated, 0 removed
822 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
822 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
823 9 additional largefiles cached
823 9 additional largefiles cached
824 $ hg -R a-clone0 sum
824 $ hg -R a-clone0 sum
825 parent: 0:30d30fe6a5be
825 parent: 0:30d30fe6a5be
826 add files
826 add files
827 branch: default
827 branch: default
828 commit: (clean)
828 commit: (clean)
829 update: 7 new changesets (update)
829 update: 7 new changesets (update)
830
830
831 $ rm "${USERCACHE}"/*
831 $ rm "${USERCACHE}"/*
832 $ hg clone --all-largefiles -u 1 a a-clone1
832 $ hg clone --all-largefiles -u 1 a a-clone1
833 updating to branch default
833 updating to branch default
834 getting changed largefiles
834 getting changed largefiles
835 2 largefiles updated, 0 removed
835 2 largefiles updated, 0 removed
836 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
836 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
837 8 additional largefiles cached
837 8 additional largefiles cached
838 $ hg -R a-clone1 verify --large --lfa --lfc
838 $ hg -R a-clone1 verify --large --lfa --lfc
839 checking changesets
839 checking changesets
840 checking manifests
840 checking manifests
841 crosschecking files in changesets and manifests
841 crosschecking files in changesets and manifests
842 checking files
842 checking files
843 10 files, 8 changesets, 24 total revisions
843 10 files, 8 changesets, 24 total revisions
844 searching 8 changesets for largefiles
844 searching 8 changesets for largefiles
845 verified contents of 13 revisions of 6 largefiles
845 verified contents of 13 revisions of 6 largefiles
846 $ hg -R a-clone1 sum
846 $ hg -R a-clone1 sum
847 parent: 1:ce8896473775
847 parent: 1:ce8896473775
848 edit files
848 edit files
849 branch: default
849 branch: default
850 commit: (clean)
850 commit: (clean)
851 update: 6 new changesets (update)
851 update: 6 new changesets (update)
852
852
853 $ rm "${USERCACHE}"/*
853 $ rm "${USERCACHE}"/*
854 $ hg clone --all-largefiles -U a a-clone-u
854 $ hg clone --all-largefiles -U a a-clone-u
855 11 additional largefiles cached
855 11 additional largefiles cached
856 $ hg -R a-clone-u sum
856 $ hg -R a-clone-u sum
857 parent: -1:000000000000 (no revision checked out)
857 parent: -1:000000000000 (no revision checked out)
858 branch: default
858 branch: default
859 commit: (clean)
859 commit: (clean)
860 update: 8 new changesets (update)
860 update: 8 new changesets (update)
861
861
862 Show computed destination directory:
862 Show computed destination directory:
863
863
864 $ mkdir xyz
864 $ mkdir xyz
865 $ cd xyz
865 $ cd xyz
866 $ hg clone ../a
866 $ hg clone ../a
867 destination directory: a
867 destination directory: a
868 updating to branch default
868 updating to branch default
869 getting changed largefiles
869 getting changed largefiles
870 3 largefiles updated, 0 removed
870 3 largefiles updated, 0 removed
871 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
871 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
872 $ cd ..
872 $ cd ..
873
873
874 Clone URL without path:
874 Clone URL without path:
875
875
876 $ hg clone file://
876 $ hg clone file://
877 abort: repository / not found!
877 abort: repository / not found!
878 [255]
878 [255]
879
879
880 Ensure base clone command argument validation
880 Ensure base clone command argument validation
881
881
882 $ hg clone -U -u 0 a a-clone-failure
882 $ hg clone -U -u 0 a a-clone-failure
883 abort: cannot specify both --noupdate and --updaterev
883 abort: cannot specify both --noupdate and --updaterev
884 [255]
884 [255]
885
885
886 $ hg clone --all-largefiles a ssh://localhost/a
886 $ hg clone --all-largefiles a ssh://localhost/a
887 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
887 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
888 [255]
888 [255]
889
889
890 Test pulling with --all-largefiles flag. Also test that the largefiles are
890 Test pulling with --all-largefiles flag. Also test that the largefiles are
891 downloaded from 'default' instead of 'default-push' when no source is specified
891 downloaded from 'default' instead of 'default-push' when no source is specified
892 (issue3584)
892 (issue3584)
893
893
894 $ rm -Rf a-backup
894 $ rm -Rf a-backup
895 $ hg clone -r 1 a a-backup
895 $ hg clone -r 1 a a-backup
896 adding changesets
896 adding changesets
897 adding manifests
897 adding manifests
898 adding file changes
898 adding file changes
899 added 2 changesets with 8 changes to 4 files
899 added 2 changesets with 8 changes to 4 files
900 updating to branch default
900 updating to branch default
901 getting changed largefiles
901 getting changed largefiles
902 2 largefiles updated, 0 removed
902 2 largefiles updated, 0 removed
903 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
903 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
904 $ rm "${USERCACHE}"/*
904 $ rm "${USERCACHE}"/*
905 $ cd a-backup
905 $ cd a-backup
906 $ hg pull --all-largefiles --config paths.default-push=bogus/path
906 $ hg pull --all-largefiles --config paths.default-push=bogus/path
907 pulling from $TESTTMP/a (glob)
907 pulling from $TESTTMP/a (glob)
908 searching for changes
908 searching for changes
909 adding changesets
909 adding changesets
910 adding manifests
910 adding manifests
911 adding file changes
911 adding file changes
912 added 6 changesets with 16 changes to 8 files
912 added 6 changesets with 16 changes to 8 files
913 (run 'hg update' to get a working copy)
913 (run 'hg update' to get a working copy)
914 6 additional largefiles cached
914 6 additional largefiles cached
915
915
916 redo pull with --lfrev and check it pulls largefiles for the right revs
916 redo pull with --lfrev and check it pulls largefiles for the right revs
917
917
918 $ hg rollback
918 $ hg rollback
919 repository tip rolled back to revision 1 (undo pull)
919 repository tip rolled back to revision 1 (undo pull)
920 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
920 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
921 pulling from $TESTTMP/a (glob)
921 pulling from $TESTTMP/a (glob)
922 searching for changes
922 searching for changes
923 all local heads known remotely
923 all local heads known remotely
924 6 changesets found
924 6 changesets found
925 adding changesets
925 adding changesets
926 adding manifests
926 adding manifests
927 adding file changes
927 adding file changes
928 added 6 changesets with 16 changes to 8 files
928 added 6 changesets with 16 changes to 8 files
929 calling hook changegroup.lfiles: <function checkrequireslfiles at *> (glob)
929 calling hook changegroup.lfiles: <function checkrequireslfiles at *> (glob)
930 (run 'hg update' to get a working copy)
930 (run 'hg update' to get a working copy)
931 pulling largefiles for revision 7
931 pulling largefiles for revision 7
932 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
932 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
933 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
933 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
934 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
934 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
935 pulling largefiles for revision 2
935 pulling largefiles for revision 2
936 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
936 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
937 0 largefiles cached
937 0 largefiles cached
938
938
939 lfpull
939 lfpull
940
940
941 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
941 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
942 2 largefiles cached
942 2 largefiles cached
943 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
943 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
944 pulling largefiles for revision 4
944 pulling largefiles for revision 4
945 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
945 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
946 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
946 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
947 pulling largefiles for revision 2
947 pulling largefiles for revision 2
948 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
948 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
949 0 largefiles cached
949 0 largefiles cached
950
950
951 $ ls usercache-lfpull/* | sort
951 $ ls usercache-lfpull/* | sort
952 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
952 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
953 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
953 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
954
954
955 $ cd ..
955 $ cd ..
956
956
957 Rebasing between two repositories does not revert largefiles to old
957 Rebasing between two repositories does not revert largefiles to old
958 revisions (this was a very bad bug that took a lot of work to fix).
958 revisions (this was a very bad bug that took a lot of work to fix).
959
959
960 $ hg clone a d
960 $ hg clone a d
961 updating to branch default
961 updating to branch default
962 getting changed largefiles
962 getting changed largefiles
963 3 largefiles updated, 0 removed
963 3 largefiles updated, 0 removed
964 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
964 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
965 $ cd b
965 $ cd b
966 $ echo large4-modified > sub/large4
966 $ echo large4-modified > sub/large4
967 $ echo normal3-modified > normal3
967 $ echo normal3-modified > normal3
968 $ hg commit -m "modify normal file and largefile in repo b"
968 $ hg commit -m "modify normal file and largefile in repo b"
969 Invoking status precommit hook
969 Invoking status precommit hook
970 M normal3
970 M normal3
971 M sub/large4
971 M sub/large4
972 $ cd ../d
972 $ cd ../d
973 $ echo large6-modified > sub2/large6
973 $ echo large6-modified > sub2/large6
974 $ echo normal4-modified > sub/normal4
974 $ echo normal4-modified > sub/normal4
975 $ hg commit -m "modify normal file largefile in repo d"
975 $ hg commit -m "modify normal file largefile in repo d"
976 Invoking status precommit hook
976 Invoking status precommit hook
977 M sub/normal4
977 M sub/normal4
978 M sub2/large6
978 M sub2/large6
979 $ cd ..
979 $ cd ..
980 $ hg clone d e
980 $ hg clone d e
981 updating to branch default
981 updating to branch default
982 getting changed largefiles
982 getting changed largefiles
983 3 largefiles updated, 0 removed
983 3 largefiles updated, 0 removed
984 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
984 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
985 $ cd d
985 $ cd d
986
986
987 More rebase testing, but also test that the largefiles are downloaded from
987 More rebase testing, but also test that the largefiles are downloaded from
988 'default-push' when no source is specified (issue3584). (The largefile from the
988 'default-push' when no source is specified (issue3584). (The largefile from the
989 pulled revision is however not downloaded but found in the local cache.)
989 pulled revision is however not downloaded but found in the local cache.)
990 Largefiles are fetched for the new pulled revision, not for existing revisions,
990 Largefiles are fetched for the new pulled revision, not for existing revisions,
991 rebased or not.
991 rebased or not.
992
992
993 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
993 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
994 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
994 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
995 pulling from $TESTTMP/b (glob)
995 pulling from $TESTTMP/b (glob)
996 searching for changes
996 searching for changes
997 adding changesets
997 adding changesets
998 adding manifests
998 adding manifests
999 adding file changes
999 adding file changes
1000 added 1 changesets with 2 changes to 2 files (+1 heads)
1000 added 1 changesets with 2 changes to 2 files (+1 heads)
1001 Invoking status precommit hook
1001 Invoking status precommit hook
1002 M sub/normal4
1002 M sub/normal4
1003 M sub2/large6
1003 M sub2/large6
1004 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1004 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1005 0 additional largefiles cached
1005 0 additional largefiles cached
1006 nothing to rebase
1006 nothing to rebase
1007 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1007 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1008 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1008 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1009 9:598410d3eb9a modify normal file largefile in repo d
1009 9:598410d3eb9a modify normal file largefile in repo d
1010 8:a381d2c8c80e modify normal file and largefile in repo b
1010 8:a381d2c8c80e modify normal file and largefile in repo b
1011 7:daea875e9014 add/edit more largefiles
1011 7:daea875e9014 add/edit more largefiles
1012 6:4355d653f84f edit files yet again
1012 6:4355d653f84f edit files yet again
1013 5:9d5af5072dbd edit files again
1013 5:9d5af5072dbd edit files again
1014 4:74c02385b94c move files
1014 4:74c02385b94c move files
1015 3:9e8fbc4bce62 copy files
1015 3:9e8fbc4bce62 copy files
1016 2:51a0ae4d5864 remove files
1016 2:51a0ae4d5864 remove files
1017 1:ce8896473775 edit files
1017 1:ce8896473775 edit files
1018 0:30d30fe6a5be add files
1018 0:30d30fe6a5be add files
1019 $ cat normal3
1019 $ cat normal3
1020 normal3-modified
1020 normal3-modified
1021 $ cat sub/normal4
1021 $ cat sub/normal4
1022 normal4-modified
1022 normal4-modified
1023 $ cat sub/large4
1023 $ cat sub/large4
1024 large4-modified
1024 large4-modified
1025 $ cat sub2/large6
1025 $ cat sub2/large6
1026 large6-modified
1026 large6-modified
1027 $ cat sub2/large7
1027 $ cat sub2/large7
1028 large7
1028 large7
1029 $ cd ../e
1029 $ cd ../e
1030 $ hg pull ../b
1030 $ hg pull ../b
1031 pulling from ../b
1031 pulling from ../b
1032 searching for changes
1032 searching for changes
1033 adding changesets
1033 adding changesets
1034 adding manifests
1034 adding manifests
1035 adding file changes
1035 adding file changes
1036 added 1 changesets with 2 changes to 2 files (+1 heads)
1036 added 1 changesets with 2 changes to 2 files (+1 heads)
1037 (run 'hg heads' to see heads, 'hg merge' to merge)
1037 (run 'hg heads' to see heads, 'hg merge' to merge)
1038 $ hg rebase
1038 $ hg rebase
1039 Invoking status precommit hook
1039 Invoking status precommit hook
1040 M sub/normal4
1040 M sub/normal4
1041 M sub2/large6
1041 M sub2/large6
1042 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1042 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1043 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1043 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1044 9:598410d3eb9a modify normal file largefile in repo d
1044 9:598410d3eb9a modify normal file largefile in repo d
1045 8:a381d2c8c80e modify normal file and largefile in repo b
1045 8:a381d2c8c80e modify normal file and largefile in repo b
1046 7:daea875e9014 add/edit more largefiles
1046 7:daea875e9014 add/edit more largefiles
1047 6:4355d653f84f edit files yet again
1047 6:4355d653f84f edit files yet again
1048 5:9d5af5072dbd edit files again
1048 5:9d5af5072dbd edit files again
1049 4:74c02385b94c move files
1049 4:74c02385b94c move files
1050 3:9e8fbc4bce62 copy files
1050 3:9e8fbc4bce62 copy files
1051 2:51a0ae4d5864 remove files
1051 2:51a0ae4d5864 remove files
1052 1:ce8896473775 edit files
1052 1:ce8896473775 edit files
1053 0:30d30fe6a5be add files
1053 0:30d30fe6a5be add files
1054 $ cat normal3
1054 $ cat normal3
1055 normal3-modified
1055 normal3-modified
1056 $ cat sub/normal4
1056 $ cat sub/normal4
1057 normal4-modified
1057 normal4-modified
1058 $ cat sub/large4
1058 $ cat sub/large4
1059 large4-modified
1059 large4-modified
1060 $ cat sub2/large6
1060 $ cat sub2/large6
1061 large6-modified
1061 large6-modified
1062 $ cat sub2/large7
1062 $ cat sub2/large7
1063 large7
1063 large7
1064
1064
1065 Log on largefiles
1065 Log on largefiles
1066
1066
1067 - same output
1067 - same output
1068 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1068 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1069 8:a381d2c8c80e modify normal file and largefile in repo b
1069 8:a381d2c8c80e modify normal file and largefile in repo b
1070 6:4355d653f84f edit files yet again
1070 6:4355d653f84f edit files yet again
1071 5:9d5af5072dbd edit files again
1071 5:9d5af5072dbd edit files again
1072 4:74c02385b94c move files
1072 4:74c02385b94c move files
1073 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1073 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1074 8:a381d2c8c80e modify normal file and largefile in repo b
1074 8:a381d2c8c80e modify normal file and largefile in repo b
1075 6:4355d653f84f edit files yet again
1075 6:4355d653f84f edit files yet again
1076 5:9d5af5072dbd edit files again
1076 5:9d5af5072dbd edit files again
1077 4:74c02385b94c move files
1077 4:74c02385b94c move files
1078
1078
1079 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1079 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1080 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1080 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1081 8:a381d2c8c80e modify normal file and largefile in repo b
1081 8:a381d2c8c80e modify normal file and largefile in repo b
1082 6:4355d653f84f edit files yet again
1082 6:4355d653f84f edit files yet again
1083 5:9d5af5072dbd edit files again
1083 5:9d5af5072dbd edit files again
1084 4:74c02385b94c move files
1084 4:74c02385b94c move files
1085 1:ce8896473775 edit files
1085 1:ce8896473775 edit files
1086 0:30d30fe6a5be add files
1086 0:30d30fe6a5be add files
1087 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1087 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1088 9:598410d3eb9a modify normal file largefile in repo d
1088 9:598410d3eb9a modify normal file largefile in repo d
1089 8:a381d2c8c80e modify normal file and largefile in repo b
1089 8:a381d2c8c80e modify normal file and largefile in repo b
1090 6:4355d653f84f edit files yet again
1090 6:4355d653f84f edit files yet again
1091 5:9d5af5072dbd edit files again
1091 5:9d5af5072dbd edit files again
1092 4:74c02385b94c move files
1092 4:74c02385b94c move files
1093 1:ce8896473775 edit files
1093 1:ce8896473775 edit files
1094 0:30d30fe6a5be add files
1094 0:30d30fe6a5be add files
1095
1095
1096 - globbing gives same result
1096 - globbing gives same result
1097 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1097 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1098 9:598410d3eb9a modify normal file largefile in repo d
1098 9:598410d3eb9a modify normal file largefile in repo d
1099 8:a381d2c8c80e modify normal file and largefile in repo b
1099 8:a381d2c8c80e modify normal file and largefile in repo b
1100 6:4355d653f84f edit files yet again
1100 6:4355d653f84f edit files yet again
1101 5:9d5af5072dbd edit files again
1101 5:9d5af5072dbd edit files again
1102 4:74c02385b94c move files
1102 4:74c02385b94c move files
1103 1:ce8896473775 edit files
1103 1:ce8896473775 edit files
1104 0:30d30fe6a5be add files
1104 0:30d30fe6a5be add files
1105
1105
1106 Rollback on largefiles.
1106 Rollback on largefiles.
1107
1107
1108 $ echo large4-modified-again > sub/large4
1108 $ echo large4-modified-again > sub/large4
1109 $ hg commit -m "Modify large4 again"
1109 $ hg commit -m "Modify large4 again"
1110 Invoking status precommit hook
1110 Invoking status precommit hook
1111 M sub/large4
1111 M sub/large4
1112 $ hg rollback
1112 $ hg rollback
1113 repository tip rolled back to revision 9 (undo commit)
1113 repository tip rolled back to revision 9 (undo commit)
1114 working directory now based on revision 9
1114 working directory now based on revision 9
1115 $ hg st
1115 $ hg st
1116 M sub/large4
1116 M sub/large4
1117 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1117 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1118 9:598410d3eb9a modify normal file largefile in repo d
1118 9:598410d3eb9a modify normal file largefile in repo d
1119 8:a381d2c8c80e modify normal file and largefile in repo b
1119 8:a381d2c8c80e modify normal file and largefile in repo b
1120 7:daea875e9014 add/edit more largefiles
1120 7:daea875e9014 add/edit more largefiles
1121 6:4355d653f84f edit files yet again
1121 6:4355d653f84f edit files yet again
1122 5:9d5af5072dbd edit files again
1122 5:9d5af5072dbd edit files again
1123 4:74c02385b94c move files
1123 4:74c02385b94c move files
1124 3:9e8fbc4bce62 copy files
1124 3:9e8fbc4bce62 copy files
1125 2:51a0ae4d5864 remove files
1125 2:51a0ae4d5864 remove files
1126 1:ce8896473775 edit files
1126 1:ce8896473775 edit files
1127 0:30d30fe6a5be add files
1127 0:30d30fe6a5be add files
1128 $ cat sub/large4
1128 $ cat sub/large4
1129 large4-modified-again
1129 large4-modified-again
1130
1130
1131 "update --check" refuses to update with uncommitted changes.
1131 "update --check" refuses to update with uncommitted changes.
1132 $ hg update --check 8
1132 $ hg update --check 8
1133 abort: uncommitted local changes
1133 abort: uncommitted local changes
1134 [255]
1134 [255]
1135
1135
1136 "update --clean" leaves correct largefiles in working copy, even when there is
1136 "update --clean" leaves correct largefiles in working copy, even when there is
1137 .orig files from revert in .hglf.
1137 .orig files from revert in .hglf.
1138
1138
1139 $ echo mistake > sub2/large7
1139 $ echo mistake > sub2/large7
1140 $ hg revert sub2/large7
1140 $ hg revert sub2/large7
1141 $ hg -q update --clean -r null
1141 $ hg -q update --clean -r null
1142 $ hg update --clean
1142 $ hg update --clean
1143 getting changed largefiles
1143 getting changed largefiles
1144 3 largefiles updated, 0 removed
1144 3 largefiles updated, 0 removed
1145 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1145 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1146 $ cat normal3
1146 $ cat normal3
1147 normal3-modified
1147 normal3-modified
1148 $ cat sub/normal4
1148 $ cat sub/normal4
1149 normal4-modified
1149 normal4-modified
1150 $ cat sub/large4
1150 $ cat sub/large4
1151 large4-modified
1151 large4-modified
1152 $ cat sub2/large6
1152 $ cat sub2/large6
1153 large6-modified
1153 large6-modified
1154 $ cat sub2/large7
1154 $ cat sub2/large7
1155 large7
1155 large7
1156 $ cat sub2/large7.orig
1156 $ cat sub2/large7.orig
1157 mistake
1157 mistake
1158 $ cat .hglf/sub2/large7.orig
1158 $ cat .hglf/sub2/large7.orig
1159 9dbfb2c79b1c40981b258c3efa1b10b03f18ad31
1159 9dbfb2c79b1c40981b258c3efa1b10b03f18ad31
1160
1160
1161 demonstrate misfeature: .orig file is overwritten on every update -C,
1161 demonstrate misfeature: .orig file is overwritten on every update -C,
1162 also when clean:
1162 also when clean:
1163 $ hg update --clean
1163 $ hg update --clean
1164 getting changed largefiles
1164 getting changed largefiles
1165 0 largefiles updated, 0 removed
1165 0 largefiles updated, 0 removed
1166 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1166 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1167 $ cat sub2/large7.orig
1167 $ cat sub2/large7.orig
1168 large7
1168 large7
1169 $ rm sub2/large7.orig .hglf/sub2/large7.orig
1169 $ rm sub2/large7.orig .hglf/sub2/large7.orig
1170
1170
1171 Now "update check" is happy.
1171 Now "update check" is happy.
1172 $ hg update --check 8
1172 $ hg update --check 8
1173 getting changed largefiles
1173 getting changed largefiles
1174 1 largefiles updated, 0 removed
1174 1 largefiles updated, 0 removed
1175 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1175 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1176 $ hg update --check
1176 $ hg update --check
1177 getting changed largefiles
1177 getting changed largefiles
1178 1 largefiles updated, 0 removed
1178 1 largefiles updated, 0 removed
1179 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1179 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1180
1180
1181 Test removing empty largefiles directories on update
1181 Test removing empty largefiles directories on update
1182 $ test -d sub2 && echo "sub2 exists"
1182 $ test -d sub2 && echo "sub2 exists"
1183 sub2 exists
1183 sub2 exists
1184 $ hg update -q null
1184 $ hg update -q null
1185 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1185 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1186 [1]
1186 [1]
1187 $ hg update -q
1187 $ hg update -q
1188
1188
1189 Test hg remove removes empty largefiles directories
1189 Test hg remove removes empty largefiles directories
1190 $ test -d sub2 && echo "sub2 exists"
1190 $ test -d sub2 && echo "sub2 exists"
1191 sub2 exists
1191 sub2 exists
1192 $ hg remove sub2/*
1192 $ hg remove sub2/*
1193 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1193 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1194 [1]
1194 [1]
1195 $ hg revert sub2/large6 sub2/large7
1195 $ hg revert sub2/large6 sub2/large7
1196
1196
1197 "revert" works on largefiles (and normal files too).
1197 "revert" works on largefiles (and normal files too).
1198 $ echo hack3 >> normal3
1198 $ echo hack3 >> normal3
1199 $ echo hack4 >> sub/normal4
1199 $ echo hack4 >> sub/normal4
1200 $ echo hack4 >> sub/large4
1200 $ echo hack4 >> sub/large4
1201 $ rm sub2/large6
1201 $ rm sub2/large6
1202 $ hg revert sub2/large6
1202 $ hg revert sub2/large6
1203 $ hg rm sub2/large6
1203 $ hg rm sub2/large6
1204 $ echo new >> sub2/large8
1204 $ echo new >> sub2/large8
1205 $ hg add --large sub2/large8
1205 $ hg add --large sub2/large8
1206 # XXX we don't really want to report that we're reverting the standin;
1206 # XXX we don't really want to report that we're reverting the standin;
1207 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1207 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1208 $ hg revert sub
1208 $ hg revert sub
1209 reverting .hglf/sub/large4 (glob)
1209 reverting .hglf/sub/large4 (glob)
1210 reverting sub/normal4 (glob)
1210 reverting sub/normal4 (glob)
1211 $ hg status
1211 $ hg status
1212 M normal3
1212 M normal3
1213 A sub2/large8
1213 A sub2/large8
1214 R sub2/large6
1214 R sub2/large6
1215 ? sub/large4.orig
1215 ? sub/large4.orig
1216 ? sub/normal4.orig
1216 ? sub/normal4.orig
1217 $ cat sub/normal4
1217 $ cat sub/normal4
1218 normal4-modified
1218 normal4-modified
1219 $ cat sub/large4
1219 $ cat sub/large4
1220 large4-modified
1220 large4-modified
1221 $ hg revert -a --no-backup
1221 $ hg revert -a --no-backup
1222 undeleting .hglf/sub2/large6 (glob)
1222 undeleting .hglf/sub2/large6 (glob)
1223 forgetting .hglf/sub2/large8 (glob)
1223 forgetting .hglf/sub2/large8 (glob)
1224 reverting normal3
1224 reverting normal3
1225 $ hg status
1225 $ hg status
1226 ? sub/large4.orig
1226 ? sub/large4.orig
1227 ? sub/normal4.orig
1227 ? sub/normal4.orig
1228 ? sub2/large8
1228 ? sub2/large8
1229 $ cat normal3
1229 $ cat normal3
1230 normal3-modified
1230 normal3-modified
1231 $ cat sub2/large6
1231 $ cat sub2/large6
1232 large6-modified
1232 large6-modified
1233 $ rm sub/*.orig sub2/large8
1233 $ rm sub/*.orig sub2/large8
1234
1234
1235 revert some files to an older revision
1235 revert some files to an older revision
1236 $ hg revert --no-backup -r 8 sub2
1236 $ hg revert --no-backup -r 8 sub2
1237 reverting .hglf/sub2/large6 (glob)
1237 reverting .hglf/sub2/large6 (glob)
1238 $ cat sub2/large6
1238 $ cat sub2/large6
1239 large6
1239 large6
1240 $ hg revert --no-backup -C -r '.^' sub2
1240 $ hg revert --no-backup -C -r '.^' sub2
1241 reverting .hglf/sub2/large6 (glob)
1241 reverting .hglf/sub2/large6 (glob)
1242 $ hg revert --no-backup sub2
1242 $ hg revert --no-backup sub2
1243 reverting .hglf/sub2/large6 (glob)
1243 reverting .hglf/sub2/large6 (glob)
1244 $ hg status
1244 $ hg status
1245
1245
1246 "verify --large" actually verifies largefiles
1246 "verify --large" actually verifies largefiles
1247
1247
1248 - Where Do We Come From? What Are We? Where Are We Going?
1248 - Where Do We Come From? What Are We? Where Are We Going?
1249 $ pwd
1249 $ pwd
1250 $TESTTMP/e
1250 $TESTTMP/e
1251 $ hg paths
1251 $ hg paths
1252 default = $TESTTMP/d (glob)
1252 default = $TESTTMP/d (glob)
1253
1253
1254 $ hg verify --large
1254 $ hg verify --large
1255 checking changesets
1255 checking changesets
1256 checking manifests
1256 checking manifests
1257 crosschecking files in changesets and manifests
1257 crosschecking files in changesets and manifests
1258 checking files
1258 checking files
1259 10 files, 10 changesets, 28 total revisions
1259 10 files, 10 changesets, 28 total revisions
1260 searching 1 changesets for largefiles
1260 searching 1 changesets for largefiles
1261 verified existence of 3 revisions of 3 largefiles
1261 verified existence of 3 revisions of 3 largefiles
1262
1262
1263 - introduce missing blob in local store repo and make sure that this is caught:
1263 - introduce missing blob in local store repo and make sure that this is caught:
1264 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1264 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1265 $ hg verify --large
1265 $ hg verify --large
1266 checking changesets
1266 checking changesets
1267 checking manifests
1267 checking manifests
1268 crosschecking files in changesets and manifests
1268 crosschecking files in changesets and manifests
1269 checking files
1269 checking files
1270 10 files, 10 changesets, 28 total revisions
1270 10 files, 10 changesets, 28 total revisions
1271 searching 1 changesets for largefiles
1271 searching 1 changesets for largefiles
1272 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1272 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1273 verified existence of 3 revisions of 3 largefiles
1273 verified existence of 3 revisions of 3 largefiles
1274 [1]
1274 [1]
1275
1275
1276 - introduce corruption and make sure that it is caught when checking content:
1276 - introduce corruption and make sure that it is caught when checking content:
1277 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1277 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1278 $ hg verify -q --large --lfc
1278 $ hg verify -q --large --lfc
1279 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1279 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1280 [1]
1280 [1]
1281
1281
1282 - cleanup
1282 - cleanup
1283 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1283 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1284
1284
1285 - verifying all revisions will fail because we didn't clone all largefiles to d:
1285 - verifying all revisions will fail because we didn't clone all largefiles to d:
1286 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1286 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1287 $ hg verify -q --lfa --lfc
1287 $ hg verify -q --lfa --lfc
1288 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1288 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1289 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1289 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1290 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1290 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1291 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1291 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1292 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1292 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1293 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1293 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1294 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1294 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1295 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1295 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1296 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1296 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1297 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1297 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1298 [1]
1298 [1]
1299
1299
1300 - cleanup
1300 - cleanup
1301 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1301 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1302 $ rm -f .hglf/sub/*.orig
1302 $ rm -f .hglf/sub/*.orig
1303
1303
1304 Update to revision with missing largefile - and make sure it really is missing
1304 Update to revision with missing largefile - and make sure it really is missing
1305
1305
1306 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1306 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1307 $ hg up -r 6
1307 $ hg up -r 6
1308 getting changed largefiles
1308 getting changed largefiles
1309 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1309 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1310 1 largefiles updated, 2 removed
1310 1 largefiles updated, 2 removed
1311 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1311 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1312 $ rm normal3
1312 $ rm normal3
1313 $ echo >> sub/normal4
1313 $ echo >> sub/normal4
1314 $ hg ci -m 'commit with missing files'
1314 $ hg ci -m 'commit with missing files'
1315 Invoking status precommit hook
1315 Invoking status precommit hook
1316 M sub/normal4
1316 M sub/normal4
1317 ! large3
1317 ! large3
1318 ! normal3
1318 ! normal3
1319 created new head
1319 created new head
1320 $ hg st
1320 $ hg st
1321 ! large3
1321 ! large3
1322 ! normal3
1322 ! normal3
1323 $ hg up -r.
1323 $ hg up -r.
1324 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1324 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1325 $ hg st
1325 $ hg st
1326 ! large3
1326 ! large3
1327 ! normal3
1327 ! normal3
1328 $ hg up -Cr.
1328 $ hg up -Cr.
1329 getting changed largefiles
1329 getting changed largefiles
1330 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1330 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1331 0 largefiles updated, 0 removed
1331 0 largefiles updated, 0 removed
1332 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1332 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1333 $ hg st
1333 $ hg st
1334 ! large3
1334 ! large3
1335 $ hg rollback
1335 $ hg rollback
1336 repository tip rolled back to revision 9 (undo commit)
1336 repository tip rolled back to revision 9 (undo commit)
1337 working directory now based on revision 6
1337 working directory now based on revision 6
1338
1338
1339 Merge with revision with missing largefile - and make sure it tries to fetch it.
1339 Merge with revision with missing largefile - and make sure it tries to fetch it.
1340
1340
1341 $ hg up -Cqr null
1341 $ hg up -Cqr null
1342 $ echo f > f
1342 $ echo f > f
1343 $ hg ci -Am branch
1343 $ hg ci -Am branch
1344 adding f
1344 adding f
1345 Invoking status precommit hook
1345 Invoking status precommit hook
1346 A f
1346 A f
1347 created new head
1347 created new head
1348 $ hg merge -r 6
1348 $ hg merge -r 6
1349 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1349 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1350 (branch merge, don't forget to commit)
1350 (branch merge, don't forget to commit)
1351 getting changed largefiles
1351 getting changed largefiles
1352 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1352 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1353 1 largefiles updated, 0 removed
1353 1 largefiles updated, 0 removed
1354
1354
1355 $ hg rollback -q
1355 $ hg rollback -q
1356 $ hg up -Cq
1356 $ hg up -Cq
1357
1357
1358 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1358 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1359
1359
1360 $ hg pull --all-largefiles
1360 $ hg pull --all-largefiles
1361 pulling from $TESTTMP/d (glob)
1361 pulling from $TESTTMP/d (glob)
1362 searching for changes
1362 searching for changes
1363 no changes found
1363 no changes found
1364 0 additional largefiles cached
1364 0 additional largefiles cached
1365
1365
1366 Merging does not revert to old versions of largefiles and also check
1366 Merging does not revert to old versions of largefiles and also check
1367 that merging after having pulled from a non-default remote works
1367 that merging after having pulled from a non-default remote works
1368 correctly.
1368 correctly.
1369
1369
1370 $ cd ..
1370 $ cd ..
1371 $ hg clone -r 7 e temp
1371 $ hg clone -r 7 e temp
1372 adding changesets
1372 adding changesets
1373 adding manifests
1373 adding manifests
1374 adding file changes
1374 adding file changes
1375 added 8 changesets with 24 changes to 10 files
1375 added 8 changesets with 24 changes to 10 files
1376 updating to branch default
1376 updating to branch default
1377 getting changed largefiles
1377 getting changed largefiles
1378 3 largefiles updated, 0 removed
1378 3 largefiles updated, 0 removed
1379 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1379 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1380 $ hg clone temp f
1380 $ hg clone temp f
1381 updating to branch default
1381 updating to branch default
1382 getting changed largefiles
1382 getting changed largefiles
1383 3 largefiles updated, 0 removed
1383 3 largefiles updated, 0 removed
1384 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1384 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1385 # Delete the largefiles in the largefiles system cache so that we have an
1385 # Delete the largefiles in the largefiles system cache so that we have an
1386 # opportunity to test that caching after a pull works.
1386 # opportunity to test that caching after a pull works.
1387 $ rm "${USERCACHE}"/*
1387 $ rm "${USERCACHE}"/*
1388 $ cd f
1388 $ cd f
1389 $ echo "large4-merge-test" > sub/large4
1389 $ echo "large4-merge-test" > sub/large4
1390 $ hg commit -m "Modify large4 to test merge"
1390 $ hg commit -m "Modify large4 to test merge"
1391 Invoking status precommit hook
1391 Invoking status precommit hook
1392 M sub/large4
1392 M sub/large4
1393 # Test --cache-largefiles flag
1393 # Test --cache-largefiles flag
1394 $ hg pull --cache-largefiles ../e
1394 $ hg pull --lfrev 'heads(pulled())' ../e
1395 pulling from ../e
1395 pulling from ../e
1396 searching for changes
1396 searching for changes
1397 adding changesets
1397 adding changesets
1398 adding manifests
1398 adding manifests
1399 adding file changes
1399 adding file changes
1400 added 2 changesets with 4 changes to 4 files (+1 heads)
1400 added 2 changesets with 4 changes to 4 files (+1 heads)
1401 (run 'hg heads' to see heads, 'hg merge' to merge)
1401 (run 'hg heads' to see heads, 'hg merge' to merge)
1402 caching largefiles for 1 heads
1403 2 largefiles cached
1402 2 largefiles cached
1404 $ hg merge
1403 $ hg merge
1405 merging sub/large4
1404 merging sub/large4
1406 largefile sub/large4 has a merge conflict
1405 largefile sub/large4 has a merge conflict
1407 keep (l)ocal or take (o)ther? l
1406 keep (l)ocal or take (o)ther? l
1408 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1407 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1409 (branch merge, don't forget to commit)
1408 (branch merge, don't forget to commit)
1410 getting changed largefiles
1409 getting changed largefiles
1411 1 largefiles updated, 0 removed
1410 1 largefiles updated, 0 removed
1412 $ hg commit -m "Merge repos e and f"
1411 $ hg commit -m "Merge repos e and f"
1413 Invoking status precommit hook
1412 Invoking status precommit hook
1414 M normal3
1413 M normal3
1415 M sub/normal4
1414 M sub/normal4
1416 M sub2/large6
1415 M sub2/large6
1417 $ cat normal3
1416 $ cat normal3
1418 normal3-modified
1417 normal3-modified
1419 $ cat sub/normal4
1418 $ cat sub/normal4
1420 normal4-modified
1419 normal4-modified
1421 $ cat sub/large4
1420 $ cat sub/large4
1422 large4-merge-test
1421 large4-merge-test
1423 $ cat sub2/large6
1422 $ cat sub2/large6
1424 large6-modified
1423 large6-modified
1425 $ cat sub2/large7
1424 $ cat sub2/large7
1426 large7
1425 large7
1427
1426
1428 Test status after merging with a branch that introduces a new largefile:
1427 Test status after merging with a branch that introduces a new largefile:
1429
1428
1430 $ echo large > large
1429 $ echo large > large
1431 $ hg add --large large
1430 $ hg add --large large
1432 $ hg commit -m 'add largefile'
1431 $ hg commit -m 'add largefile'
1433 Invoking status precommit hook
1432 Invoking status precommit hook
1434 A large
1433 A large
1435 $ hg update -q ".^"
1434 $ hg update -q ".^"
1436 $ echo change >> normal3
1435 $ echo change >> normal3
1437 $ hg commit -m 'some change'
1436 $ hg commit -m 'some change'
1438 Invoking status precommit hook
1437 Invoking status precommit hook
1439 M normal3
1438 M normal3
1440 created new head
1439 created new head
1441 $ hg merge
1440 $ hg merge
1442 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1443 (branch merge, don't forget to commit)
1442 (branch merge, don't forget to commit)
1444 getting changed largefiles
1443 getting changed largefiles
1445 1 largefiles updated, 0 removed
1444 1 largefiles updated, 0 removed
1446 $ hg status
1445 $ hg status
1447 M large
1446 M large
1448
1447
1449 - make sure update of merge with removed largefiles fails as expected
1448 - make sure update of merge with removed largefiles fails as expected
1450 $ hg rm sub2/large6
1449 $ hg rm sub2/large6
1451 $ hg up -r.
1450 $ hg up -r.
1452 abort: outstanding uncommitted merges
1451 abort: outstanding uncommitted merges
1453 [255]
1452 [255]
1454
1453
1455 - revert should be able to revert files introduced in a pending merge
1454 - revert should be able to revert files introduced in a pending merge
1456 $ hg revert --all -r .
1455 $ hg revert --all -r .
1457 removing .hglf/large (glob)
1456 removing .hglf/large (glob)
1458 undeleting .hglf/sub2/large6 (glob)
1457 undeleting .hglf/sub2/large6 (glob)
1459
1458
1460 Test that a normal file and a largefile with the same name and path cannot
1459 Test that a normal file and a largefile with the same name and path cannot
1461 coexist.
1460 coexist.
1462
1461
1463 $ rm sub2/large7
1462 $ rm sub2/large7
1464 $ echo "largeasnormal" > sub2/large7
1463 $ echo "largeasnormal" > sub2/large7
1465 $ hg add sub2/large7
1464 $ hg add sub2/large7
1466 sub2/large7 already a largefile
1465 sub2/large7 already a largefile
1467
1466
1468 Test that transplanting a largefile change works correctly.
1467 Test that transplanting a largefile change works correctly.
1469
1468
1470 $ cd ..
1469 $ cd ..
1471 $ hg clone -r 8 d g
1470 $ hg clone -r 8 d g
1472 adding changesets
1471 adding changesets
1473 adding manifests
1472 adding manifests
1474 adding file changes
1473 adding file changes
1475 added 9 changesets with 26 changes to 10 files
1474 added 9 changesets with 26 changes to 10 files
1476 updating to branch default
1475 updating to branch default
1477 getting changed largefiles
1476 getting changed largefiles
1478 3 largefiles updated, 0 removed
1477 3 largefiles updated, 0 removed
1479 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1478 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1480 $ cd g
1479 $ cd g
1481 $ hg transplant -s ../d 598410d3eb9a
1480 $ hg transplant -s ../d 598410d3eb9a
1482 searching for changes
1481 searching for changes
1483 searching for changes
1482 searching for changes
1484 adding changesets
1483 adding changesets
1485 adding manifests
1484 adding manifests
1486 adding file changes
1485 adding file changes
1487 added 1 changesets with 2 changes to 2 files
1486 added 1 changesets with 2 changes to 2 files
1488 getting changed largefiles
1487 getting changed largefiles
1489 1 largefiles updated, 0 removed
1488 1 largefiles updated, 0 removed
1490 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1489 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1491 9:598410d3eb9a modify normal file largefile in repo d
1490 9:598410d3eb9a modify normal file largefile in repo d
1492 8:a381d2c8c80e modify normal file and largefile in repo b
1491 8:a381d2c8c80e modify normal file and largefile in repo b
1493 7:daea875e9014 add/edit more largefiles
1492 7:daea875e9014 add/edit more largefiles
1494 6:4355d653f84f edit files yet again
1493 6:4355d653f84f edit files yet again
1495 5:9d5af5072dbd edit files again
1494 5:9d5af5072dbd edit files again
1496 4:74c02385b94c move files
1495 4:74c02385b94c move files
1497 3:9e8fbc4bce62 copy files
1496 3:9e8fbc4bce62 copy files
1498 2:51a0ae4d5864 remove files
1497 2:51a0ae4d5864 remove files
1499 1:ce8896473775 edit files
1498 1:ce8896473775 edit files
1500 0:30d30fe6a5be add files
1499 0:30d30fe6a5be add files
1501 $ cat normal3
1500 $ cat normal3
1502 normal3-modified
1501 normal3-modified
1503 $ cat sub/normal4
1502 $ cat sub/normal4
1504 normal4-modified
1503 normal4-modified
1505 $ cat sub/large4
1504 $ cat sub/large4
1506 large4-modified
1505 large4-modified
1507 $ cat sub2/large6
1506 $ cat sub2/large6
1508 large6-modified
1507 large6-modified
1509 $ cat sub2/large7
1508 $ cat sub2/large7
1510 large7
1509 large7
1511
1510
1512 Cat a largefile
1511 Cat a largefile
1513 $ hg cat normal3
1512 $ hg cat normal3
1514 normal3-modified
1513 normal3-modified
1515 $ hg cat sub/large4
1514 $ hg cat sub/large4
1516 large4-modified
1515 large4-modified
1517 $ rm "${USERCACHE}"/*
1516 $ rm "${USERCACHE}"/*
1518 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1517 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1519 $ cat cat.out
1518 $ cat cat.out
1520 large4-modified
1519 large4-modified
1521 $ rm cat.out
1520 $ rm cat.out
1522 $ hg cat -r a381d2c8c80e normal3
1521 $ hg cat -r a381d2c8c80e normal3
1523 normal3-modified
1522 normal3-modified
1524 $ hg cat -r '.^' normal3
1523 $ hg cat -r '.^' normal3
1525 normal3-modified
1524 normal3-modified
1526 $ hg cat -r '.^' sub/large4 doesntexist
1525 $ hg cat -r '.^' sub/large4 doesntexist
1527 large4-modified
1526 large4-modified
1528 doesntexist: no such file in rev a381d2c8c80e
1527 doesntexist: no such file in rev a381d2c8c80e
1529 $ hg --cwd sub cat -r '.^' large4
1528 $ hg --cwd sub cat -r '.^' large4
1530 large4-modified
1529 large4-modified
1531 $ hg --cwd sub cat -r '.^' ../normal3
1530 $ hg --cwd sub cat -r '.^' ../normal3
1532 normal3-modified
1531 normal3-modified
1533
1532
1534 Test that renaming a largefile results in correct output for status
1533 Test that renaming a largefile results in correct output for status
1535
1534
1536 $ hg rename sub/large4 large4-renamed
1535 $ hg rename sub/large4 large4-renamed
1537 $ hg commit -m "test rename output"
1536 $ hg commit -m "test rename output"
1538 Invoking status precommit hook
1537 Invoking status precommit hook
1539 A large4-renamed
1538 A large4-renamed
1540 R sub/large4
1539 R sub/large4
1541 $ cat large4-renamed
1540 $ cat large4-renamed
1542 large4-modified
1541 large4-modified
1543 $ cd sub2
1542 $ cd sub2
1544 $ hg rename large6 large6-renamed
1543 $ hg rename large6 large6-renamed
1545 $ hg st
1544 $ hg st
1546 A sub2/large6-renamed
1545 A sub2/large6-renamed
1547 R sub2/large6
1546 R sub2/large6
1548 $ cd ..
1547 $ cd ..
1549
1548
1550 Test --normal flag
1549 Test --normal flag
1551
1550
1552 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1551 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1553 $ hg add --normal --large new-largefile
1552 $ hg add --normal --large new-largefile
1554 abort: --normal cannot be used with --large
1553 abort: --normal cannot be used with --large
1555 [255]
1554 [255]
1556 $ hg add --normal new-largefile
1555 $ hg add --normal new-largefile
1557 new-largefile: up to 69 MB of RAM may be required to manage this file
1556 new-largefile: up to 69 MB of RAM may be required to manage this file
1558 (use 'hg revert new-largefile' to cancel the pending addition)
1557 (use 'hg revert new-largefile' to cancel the pending addition)
1559 $ cd ..
1558 $ cd ..
1560
1559
1561 #if serve
1560 #if serve
1562 vanilla clients not locked out from largefiles servers on vanilla repos
1561 vanilla clients not locked out from largefiles servers on vanilla repos
1563 $ mkdir r1
1562 $ mkdir r1
1564 $ cd r1
1563 $ cd r1
1565 $ hg init
1564 $ hg init
1566 $ echo c1 > f1
1565 $ echo c1 > f1
1567 $ hg add f1
1566 $ hg add f1
1568 $ hg commit -m "m1"
1567 $ hg commit -m "m1"
1569 Invoking status precommit hook
1568 Invoking status precommit hook
1570 A f1
1569 A f1
1571 $ cd ..
1570 $ cd ..
1572 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1571 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1573 $ cat hg.pid >> $DAEMON_PIDS
1572 $ cat hg.pid >> $DAEMON_PIDS
1574 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1573 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1575 requesting all changes
1574 requesting all changes
1576 adding changesets
1575 adding changesets
1577 adding manifests
1576 adding manifests
1578 adding file changes
1577 adding file changes
1579 added 1 changesets with 1 changes to 1 files
1578 added 1 changesets with 1 changes to 1 files
1580 updating to branch default
1579 updating to branch default
1581 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1580 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1582
1581
1583 largefiles clients still work with vanilla servers
1582 largefiles clients still work with vanilla servers
1584 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1583 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1585 $ cat hg.pid >> $DAEMON_PIDS
1584 $ cat hg.pid >> $DAEMON_PIDS
1586 $ hg clone http://localhost:$HGPORT1 r3
1585 $ hg clone http://localhost:$HGPORT1 r3
1587 requesting all changes
1586 requesting all changes
1588 adding changesets
1587 adding changesets
1589 adding manifests
1588 adding manifests
1590 adding file changes
1589 adding file changes
1591 added 1 changesets with 1 changes to 1 files
1590 added 1 changesets with 1 changes to 1 files
1592 updating to branch default
1591 updating to branch default
1593 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1592 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1594 #endif
1593 #endif
1595
1594
1596
1595
1597 vanilla clients locked out from largefiles http repos
1596 vanilla clients locked out from largefiles http repos
1598 $ mkdir r4
1597 $ mkdir r4
1599 $ cd r4
1598 $ cd r4
1600 $ hg init
1599 $ hg init
1601 $ echo c1 > f1
1600 $ echo c1 > f1
1602 $ hg add --large f1
1601 $ hg add --large f1
1603 $ hg commit -m "m1"
1602 $ hg commit -m "m1"
1604 Invoking status precommit hook
1603 Invoking status precommit hook
1605 A f1
1604 A f1
1606 $ cd ..
1605 $ cd ..
1607
1606
1608 largefiles can be pushed locally (issue3583)
1607 largefiles can be pushed locally (issue3583)
1609 $ hg init dest
1608 $ hg init dest
1610 $ cd r4
1609 $ cd r4
1611 $ hg outgoing ../dest
1610 $ hg outgoing ../dest
1612 comparing with ../dest
1611 comparing with ../dest
1613 searching for changes
1612 searching for changes
1614 changeset: 0:639881c12b4c
1613 changeset: 0:639881c12b4c
1615 tag: tip
1614 tag: tip
1616 user: test
1615 user: test
1617 date: Thu Jan 01 00:00:00 1970 +0000
1616 date: Thu Jan 01 00:00:00 1970 +0000
1618 summary: m1
1617 summary: m1
1619
1618
1620 $ hg push ../dest
1619 $ hg push ../dest
1621 pushing to ../dest
1620 pushing to ../dest
1622 searching for changes
1621 searching for changes
1623 searching for changes
1622 searching for changes
1624 adding changesets
1623 adding changesets
1625 adding manifests
1624 adding manifests
1626 adding file changes
1625 adding file changes
1627 added 1 changesets with 1 changes to 1 files
1626 added 1 changesets with 1 changes to 1 files
1628
1627
1629 exit code with nothing outgoing (issue3611)
1628 exit code with nothing outgoing (issue3611)
1630 $ hg outgoing ../dest
1629 $ hg outgoing ../dest
1631 comparing with ../dest
1630 comparing with ../dest
1632 searching for changes
1631 searching for changes
1633 no changes found
1632 no changes found
1634 [1]
1633 [1]
1635 $ cd ..
1634 $ cd ..
1636
1635
1637 #if serve
1636 #if serve
1638 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1637 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1639 $ cat hg.pid >> $DAEMON_PIDS
1638 $ cat hg.pid >> $DAEMON_PIDS
1640 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1639 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1641 abort: remote error:
1640 abort: remote error:
1642
1641
1643 This repository uses the largefiles extension.
1642 This repository uses the largefiles extension.
1644
1643
1645 Please enable it in your Mercurial config file.
1644 Please enable it in your Mercurial config file.
1646 [255]
1645 [255]
1647
1646
1648 used all HGPORTs, kill all daemons
1647 used all HGPORTs, kill all daemons
1649 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1648 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1650 #endif
1649 #endif
1651
1650
1652 vanilla clients locked out from largefiles ssh repos
1651 vanilla clients locked out from largefiles ssh repos
1653 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1652 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1654 abort: remote error:
1653 abort: remote error:
1655
1654
1656 This repository uses the largefiles extension.
1655 This repository uses the largefiles extension.
1657
1656
1658 Please enable it in your Mercurial config file.
1657 Please enable it in your Mercurial config file.
1659 [255]
1658 [255]
1660
1659
1661 #if serve
1660 #if serve
1662
1661
1663 largefiles clients refuse to push largefiles repos to vanilla servers
1662 largefiles clients refuse to push largefiles repos to vanilla servers
1664 $ mkdir r6
1663 $ mkdir r6
1665 $ cd r6
1664 $ cd r6
1666 $ hg init
1665 $ hg init
1667 $ echo c1 > f1
1666 $ echo c1 > f1
1668 $ hg add f1
1667 $ hg add f1
1669 $ hg commit -m "m1"
1668 $ hg commit -m "m1"
1670 Invoking status precommit hook
1669 Invoking status precommit hook
1671 A f1
1670 A f1
1672 $ cat >> .hg/hgrc <<!
1671 $ cat >> .hg/hgrc <<!
1673 > [web]
1672 > [web]
1674 > push_ssl = false
1673 > push_ssl = false
1675 > allow_push = *
1674 > allow_push = *
1676 > !
1675 > !
1677 $ cd ..
1676 $ cd ..
1678 $ hg clone r6 r7
1677 $ hg clone r6 r7
1679 updating to branch default
1678 updating to branch default
1680 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1679 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1681 $ cd r7
1680 $ cd r7
1682 $ echo c2 > f2
1681 $ echo c2 > f2
1683 $ hg add --large f2
1682 $ hg add --large f2
1684 $ hg commit -m "m2"
1683 $ hg commit -m "m2"
1685 Invoking status precommit hook
1684 Invoking status precommit hook
1686 A f2
1685 A f2
1687 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1686 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1688 $ cat ../hg.pid >> $DAEMON_PIDS
1687 $ cat ../hg.pid >> $DAEMON_PIDS
1689 $ hg push http://localhost:$HGPORT
1688 $ hg push http://localhost:$HGPORT
1690 pushing to http://localhost:$HGPORT/
1689 pushing to http://localhost:$HGPORT/
1691 searching for changes
1690 searching for changes
1692 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1691 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1693 [255]
1692 [255]
1694 $ cd ..
1693 $ cd ..
1695
1694
1696 putlfile errors are shown (issue3123)
1695 putlfile errors are shown (issue3123)
1697 Corrupt the cached largefile in r7 and move it out of the servers usercache
1696 Corrupt the cached largefile in r7 and move it out of the servers usercache
1698 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
1697 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
1699 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1698 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1700 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1699 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1701 $ hg init empty
1700 $ hg init empty
1702 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1701 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1703 > --config 'web.allow_push=*' --config web.push_ssl=False
1702 > --config 'web.allow_push=*' --config web.push_ssl=False
1704 $ cat hg.pid >> $DAEMON_PIDS
1703 $ cat hg.pid >> $DAEMON_PIDS
1705 $ hg push -R r7 http://localhost:$HGPORT1
1704 $ hg push -R r7 http://localhost:$HGPORT1
1706 pushing to http://localhost:$HGPORT1/
1705 pushing to http://localhost:$HGPORT1/
1707 searching for changes
1706 searching for changes
1708 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1707 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1709 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1708 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1710 [255]
1709 [255]
1711 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1710 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1712 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
1711 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
1713 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1712 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1714 $ hg push -R r7 http://localhost:$HGPORT1
1713 $ hg push -R r7 http://localhost:$HGPORT1
1715 pushing to http://localhost:$HGPORT1/
1714 pushing to http://localhost:$HGPORT1/
1716 searching for changes
1715 searching for changes
1717 searching for changes
1716 searching for changes
1718 remote: adding changesets
1717 remote: adding changesets
1719 remote: adding manifests
1718 remote: adding manifests
1720 remote: adding file changes
1719 remote: adding file changes
1721 remote: added 2 changesets with 2 changes to 2 files
1720 remote: added 2 changesets with 2 changes to 2 files
1722 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1721 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1723 server side corruption
1722 server side corruption
1724 $ rm -rf empty
1723 $ rm -rf empty
1725
1724
1726 Push a largefiles repository to a served empty repository
1725 Push a largefiles repository to a served empty repository
1727 $ hg init r8
1726 $ hg init r8
1728 $ echo c3 > r8/f1
1727 $ echo c3 > r8/f1
1729 $ hg add --large r8/f1 -R r8
1728 $ hg add --large r8/f1 -R r8
1730 $ hg commit -m "m1" -R r8
1729 $ hg commit -m "m1" -R r8
1731 Invoking status precommit hook
1730 Invoking status precommit hook
1732 A f1
1731 A f1
1733 $ hg init empty
1732 $ hg init empty
1734 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1733 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1735 > --config 'web.allow_push=*' --config web.push_ssl=False
1734 > --config 'web.allow_push=*' --config web.push_ssl=False
1736 $ cat hg.pid >> $DAEMON_PIDS
1735 $ cat hg.pid >> $DAEMON_PIDS
1737 $ rm "${USERCACHE}"/*
1736 $ rm "${USERCACHE}"/*
1738 $ hg push -R r8 http://localhost:$HGPORT2/#default
1737 $ hg push -R r8 http://localhost:$HGPORT2/#default
1739 pushing to http://localhost:$HGPORT2/
1738 pushing to http://localhost:$HGPORT2/
1740 searching for changes
1739 searching for changes
1741 searching for changes
1740 searching for changes
1742 remote: adding changesets
1741 remote: adding changesets
1743 remote: adding manifests
1742 remote: adding manifests
1744 remote: adding file changes
1743 remote: adding file changes
1745 remote: added 1 changesets with 1 changes to 1 files
1744 remote: added 1 changesets with 1 changes to 1 files
1746 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1745 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1747 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1746 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1748
1747
1749 Clone over http, no largefiles pulled on clone.
1748 Clone over http, no largefiles pulled on clone.
1750
1749
1751 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
1750 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
1752 adding changesets
1751 adding changesets
1753 adding manifests
1752 adding manifests
1754 adding file changes
1753 adding file changes
1755 added 1 changesets with 1 changes to 1 files
1754 added 1 changesets with 1 changes to 1 files
1756
1755
1757 test 'verify' with remotestore:
1756 test 'verify' with remotestore:
1758
1757
1759 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
1758 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
1760 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1759 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1761 $ hg -R http-clone verify --large --lfa
1760 $ hg -R http-clone verify --large --lfa
1762 checking changesets
1761 checking changesets
1763 checking manifests
1762 checking manifests
1764 crosschecking files in changesets and manifests
1763 crosschecking files in changesets and manifests
1765 checking files
1764 checking files
1766 1 files, 1 changesets, 1 total revisions
1765 1 files, 1 changesets, 1 total revisions
1767 searching 1 changesets for largefiles
1766 searching 1 changesets for largefiles
1768 changeset 0:cf03e5bb9936: f1 missing
1767 changeset 0:cf03e5bb9936: f1 missing
1769 verified existence of 1 revisions of 1 largefiles
1768 verified existence of 1 revisions of 1 largefiles
1770 [1]
1769 [1]
1771 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1770 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1772 $ hg -R http-clone -q verify --large --lfa
1771 $ hg -R http-clone -q verify --large --lfa
1773
1772
1774 largefiles pulled on update - a largefile missing on the server:
1773 largefiles pulled on update - a largefile missing on the server:
1775 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1774 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1776 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1775 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1777 getting changed largefiles
1776 getting changed largefiles
1778 abort: remotestore: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 is missing
1777 abort: remotestore: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 is missing
1779 [255]
1778 [255]
1780 $ hg -R http-clone up -Cqr null
1779 $ hg -R http-clone up -Cqr null
1781
1780
1782 largefiles pulled on update - a largefile corrupted on the server:
1781 largefiles pulled on update - a largefile corrupted on the server:
1783 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
1782 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
1784 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1783 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1785 getting changed largefiles
1784 getting changed largefiles
1786 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
1785 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
1787 0 largefiles updated, 0 removed
1786 0 largefiles updated, 0 removed
1788 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1787 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1789 $ hg -R http-clone st
1788 $ hg -R http-clone st
1790 ! f1
1789 ! f1
1791 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1790 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1792 $ [ ! -f http-clone/f1 ]
1791 $ [ ! -f http-clone/f1 ]
1793 $ [ ! -f http-clone-usercache ]
1792 $ [ ! -f http-clone-usercache ]
1794 $ hg -R http-clone verify --large --lfc
1793 $ hg -R http-clone verify --large --lfc
1795 checking changesets
1794 checking changesets
1796 checking manifests
1795 checking manifests
1797 crosschecking files in changesets and manifests
1796 crosschecking files in changesets and manifests
1798 checking files
1797 checking files
1799 1 files, 1 changesets, 1 total revisions
1798 1 files, 1 changesets, 1 total revisions
1800 searching 1 changesets for largefiles
1799 searching 1 changesets for largefiles
1801 verified contents of 1 revisions of 1 largefiles
1800 verified contents of 1 revisions of 1 largefiles
1802 $ hg -R http-clone up -Cqr null
1801 $ hg -R http-clone up -Cqr null
1803
1802
1804 largefiles pulled on update - no server side problems:
1803 largefiles pulled on update - no server side problems:
1805 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1804 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1806 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
1805 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
1807 resolving manifests
1806 resolving manifests
1808 branchmerge: False, force: False, partial: False
1807 branchmerge: False, force: False, partial: False
1809 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
1808 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
1810 .hglf/f1: remote created -> g
1809 .hglf/f1: remote created -> g
1811 getting .hglf/f1
1810 getting .hglf/f1
1812 updating: .hglf/f1 1/1 files (100.00%)
1811 updating: .hglf/f1 1/1 files (100.00%)
1813 getting changed largefiles
1812 getting changed largefiles
1814 using http://localhost:$HGPORT2/
1813 using http://localhost:$HGPORT2/
1815 sending capabilities command
1814 sending capabilities command
1816 getting largefiles: 0/1 lfile (0.00%)
1815 getting largefiles: 0/1 lfile (0.00%)
1817 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
1816 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
1818 sending batch command
1817 sending batch command
1819 sending getlfile command
1818 sending getlfile command
1820 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
1819 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
1821 1 largefiles updated, 0 removed
1820 1 largefiles updated, 0 removed
1822 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1821 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1823
1822
1824 $ ls http-clone-usercache/*
1823 $ ls http-clone-usercache/*
1825 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
1824 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
1826
1825
1827 $ rm -rf empty http-clone*
1826 $ rm -rf empty http-clone*
1828
1827
1829 used all HGPORTs, kill all daemons
1828 used all HGPORTs, kill all daemons
1830 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1829 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1831
1830
1832 #endif
1831 #endif
1833
1832
1834
1833
1835 #if unix-permissions
1834 #if unix-permissions
1836
1835
1837 Clone a local repository owned by another user
1836 Clone a local repository owned by another user
1838 We have to simulate that here by setting $HOME and removing write permissions
1837 We have to simulate that here by setting $HOME and removing write permissions
1839 $ ORIGHOME="$HOME"
1838 $ ORIGHOME="$HOME"
1840 $ mkdir alice
1839 $ mkdir alice
1841 $ HOME="`pwd`/alice"
1840 $ HOME="`pwd`/alice"
1842 $ cd alice
1841 $ cd alice
1843 $ hg init pubrepo
1842 $ hg init pubrepo
1844 $ cd pubrepo
1843 $ cd pubrepo
1845 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1844 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1846 $ hg add --large a-large-file
1845 $ hg add --large a-large-file
1847 $ hg commit -m "Add a large file"
1846 $ hg commit -m "Add a large file"
1848 Invoking status precommit hook
1847 Invoking status precommit hook
1849 A a-large-file
1848 A a-large-file
1850 $ cd ..
1849 $ cd ..
1851 $ chmod -R a-w pubrepo
1850 $ chmod -R a-w pubrepo
1852 $ cd ..
1851 $ cd ..
1853 $ mkdir bob
1852 $ mkdir bob
1854 $ HOME="`pwd`/bob"
1853 $ HOME="`pwd`/bob"
1855 $ cd bob
1854 $ cd bob
1856 $ hg clone --pull ../alice/pubrepo pubrepo
1855 $ hg clone --pull ../alice/pubrepo pubrepo
1857 requesting all changes
1856 requesting all changes
1858 adding changesets
1857 adding changesets
1859 adding manifests
1858 adding manifests
1860 adding file changes
1859 adding file changes
1861 added 1 changesets with 1 changes to 1 files
1860 added 1 changesets with 1 changes to 1 files
1862 updating to branch default
1861 updating to branch default
1863 getting changed largefiles
1862 getting changed largefiles
1864 1 largefiles updated, 0 removed
1863 1 largefiles updated, 0 removed
1865 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1864 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1866 $ cd ..
1865 $ cd ..
1867 $ chmod -R u+w alice/pubrepo
1866 $ chmod -R u+w alice/pubrepo
1868 $ HOME="$ORIGHOME"
1867 $ HOME="$ORIGHOME"
1869
1868
1870 #endif
1869 #endif
1871
1870
1872 #if symlink
1871 #if symlink
1873
1872
1874 Symlink to a large largefile should behave the same as a symlink to a normal file
1873 Symlink to a large largefile should behave the same as a symlink to a normal file
1875 $ hg init largesymlink
1874 $ hg init largesymlink
1876 $ cd largesymlink
1875 $ cd largesymlink
1877 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1876 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1878 $ hg add --large largefile
1877 $ hg add --large largefile
1879 $ hg commit -m "commit a large file"
1878 $ hg commit -m "commit a large file"
1880 Invoking status precommit hook
1879 Invoking status precommit hook
1881 A largefile
1880 A largefile
1882 $ ln -s largefile largelink
1881 $ ln -s largefile largelink
1883 $ hg add largelink
1882 $ hg add largelink
1884 $ hg commit -m "commit a large symlink"
1883 $ hg commit -m "commit a large symlink"
1885 Invoking status precommit hook
1884 Invoking status precommit hook
1886 A largelink
1885 A largelink
1887 $ rm -f largelink
1886 $ rm -f largelink
1888 $ hg up >/dev/null
1887 $ hg up >/dev/null
1889 $ test -f largelink
1888 $ test -f largelink
1890 [1]
1889 [1]
1891 $ test -L largelink
1890 $ test -L largelink
1892 [1]
1891 [1]
1893 $ rm -f largelink # make next part of the test independent of the previous
1892 $ rm -f largelink # make next part of the test independent of the previous
1894 $ hg up -C >/dev/null
1893 $ hg up -C >/dev/null
1895 $ test -f largelink
1894 $ test -f largelink
1896 $ test -L largelink
1895 $ test -L largelink
1897 $ cd ..
1896 $ cd ..
1898
1897
1899 #endif
1898 #endif
1900
1899
1901 test for pattern matching on 'hg status':
1900 test for pattern matching on 'hg status':
1902 to boost performance, largefiles checks whether specified patterns are
1901 to boost performance, largefiles checks whether specified patterns are
1903 related to largefiles in working directory (NOT to STANDIN) or not.
1902 related to largefiles in working directory (NOT to STANDIN) or not.
1904
1903
1905 $ hg init statusmatch
1904 $ hg init statusmatch
1906 $ cd statusmatch
1905 $ cd statusmatch
1907
1906
1908 $ mkdir -p a/b/c/d
1907 $ mkdir -p a/b/c/d
1909 $ echo normal > a/b/c/d/e.normal.txt
1908 $ echo normal > a/b/c/d/e.normal.txt
1910 $ hg add a/b/c/d/e.normal.txt
1909 $ hg add a/b/c/d/e.normal.txt
1911 $ echo large > a/b/c/d/e.large.txt
1910 $ echo large > a/b/c/d/e.large.txt
1912 $ hg add --large a/b/c/d/e.large.txt
1911 $ hg add --large a/b/c/d/e.large.txt
1913 $ mkdir -p a/b/c/x
1912 $ mkdir -p a/b/c/x
1914 $ echo normal > a/b/c/x/y.normal.txt
1913 $ echo normal > a/b/c/x/y.normal.txt
1915 $ hg add a/b/c/x/y.normal.txt
1914 $ hg add a/b/c/x/y.normal.txt
1916 $ hg commit -m 'add files'
1915 $ hg commit -m 'add files'
1917 Invoking status precommit hook
1916 Invoking status precommit hook
1918 A a/b/c/d/e.large.txt
1917 A a/b/c/d/e.large.txt
1919 A a/b/c/d/e.normal.txt
1918 A a/b/c/d/e.normal.txt
1920 A a/b/c/x/y.normal.txt
1919 A a/b/c/x/y.normal.txt
1921
1920
1922 (1) no pattern: no performance boost
1921 (1) no pattern: no performance boost
1923 $ hg status -A
1922 $ hg status -A
1924 C a/b/c/d/e.large.txt
1923 C a/b/c/d/e.large.txt
1925 C a/b/c/d/e.normal.txt
1924 C a/b/c/d/e.normal.txt
1926 C a/b/c/x/y.normal.txt
1925 C a/b/c/x/y.normal.txt
1927
1926
1928 (2) pattern not related to largefiles: performance boost
1927 (2) pattern not related to largefiles: performance boost
1929 $ hg status -A a/b/c/x
1928 $ hg status -A a/b/c/x
1930 C a/b/c/x/y.normal.txt
1929 C a/b/c/x/y.normal.txt
1931
1930
1932 (3) pattern related to largefiles: no performance boost
1931 (3) pattern related to largefiles: no performance boost
1933 $ hg status -A a/b/c/d
1932 $ hg status -A a/b/c/d
1934 C a/b/c/d/e.large.txt
1933 C a/b/c/d/e.large.txt
1935 C a/b/c/d/e.normal.txt
1934 C a/b/c/d/e.normal.txt
1936
1935
1937 (4) pattern related to STANDIN (not to largefiles): performance boost
1936 (4) pattern related to STANDIN (not to largefiles): performance boost
1938 $ hg status -A .hglf/a
1937 $ hg status -A .hglf/a
1939 C .hglf/a/b/c/d/e.large.txt
1938 C .hglf/a/b/c/d/e.large.txt
1940
1939
1941 (5) mixed case: no performance boost
1940 (5) mixed case: no performance boost
1942 $ hg status -A a/b/c/x a/b/c/d
1941 $ hg status -A a/b/c/x a/b/c/d
1943 C a/b/c/d/e.large.txt
1942 C a/b/c/d/e.large.txt
1944 C a/b/c/d/e.normal.txt
1943 C a/b/c/d/e.normal.txt
1945 C a/b/c/x/y.normal.txt
1944 C a/b/c/x/y.normal.txt
1946
1945
1947 verify that largefiles doesn't break filesets
1946 verify that largefiles doesn't break filesets
1948
1947
1949 $ hg log --rev . --exclude "set:binary()"
1948 $ hg log --rev . --exclude "set:binary()"
1950 changeset: 0:41bd42f10efa
1949 changeset: 0:41bd42f10efa
1951 tag: tip
1950 tag: tip
1952 user: test
1951 user: test
1953 date: Thu Jan 01 00:00:00 1970 +0000
1952 date: Thu Jan 01 00:00:00 1970 +0000
1954 summary: add files
1953 summary: add files
1955
1954
1956 verify that large files in subrepos handled properly
1955 verify that large files in subrepos handled properly
1957 $ hg init subrepo
1956 $ hg init subrepo
1958 $ echo "subrepo = subrepo" > .hgsub
1957 $ echo "subrepo = subrepo" > .hgsub
1959 $ hg add .hgsub
1958 $ hg add .hgsub
1960 $ hg ci -m "add subrepo"
1959 $ hg ci -m "add subrepo"
1961 Invoking status precommit hook
1960 Invoking status precommit hook
1962 A .hgsub
1961 A .hgsub
1963 ? .hgsubstate
1962 ? .hgsubstate
1964 $ echo "rev 1" > subrepo/large.txt
1963 $ echo "rev 1" > subrepo/large.txt
1965 $ hg -R subrepo add --large subrepo/large.txt
1964 $ hg -R subrepo add --large subrepo/large.txt
1966 $ hg sum
1965 $ hg sum
1967 parent: 1:8ee150ea2e9c tip
1966 parent: 1:8ee150ea2e9c tip
1968 add subrepo
1967 add subrepo
1969 branch: default
1968 branch: default
1970 commit: 1 subrepos
1969 commit: 1 subrepos
1971 update: (current)
1970 update: (current)
1972 $ hg st
1971 $ hg st
1973 $ hg st -S
1972 $ hg st -S
1974 A subrepo/large.txt
1973 A subrepo/large.txt
1975 $ hg ci -S -m "commit top repo"
1974 $ hg ci -S -m "commit top repo"
1976 committing subrepository subrepo
1975 committing subrepository subrepo
1977 Invoking status precommit hook
1976 Invoking status precommit hook
1978 A large.txt
1977 A large.txt
1979 Invoking status precommit hook
1978 Invoking status precommit hook
1980 M .hgsubstate
1979 M .hgsubstate
1981 # No differences
1980 # No differences
1982 $ hg st -S
1981 $ hg st -S
1983 $ hg sum
1982 $ hg sum
1984 parent: 2:ce4cd0c527a6 tip
1983 parent: 2:ce4cd0c527a6 tip
1985 commit top repo
1984 commit top repo
1986 branch: default
1985 branch: default
1987 commit: (clean)
1986 commit: (clean)
1988 update: (current)
1987 update: (current)
1989 $ echo "rev 2" > subrepo/large.txt
1988 $ echo "rev 2" > subrepo/large.txt
1990 $ hg st -S
1989 $ hg st -S
1991 M subrepo/large.txt
1990 M subrepo/large.txt
1992 $ hg sum
1991 $ hg sum
1993 parent: 2:ce4cd0c527a6 tip
1992 parent: 2:ce4cd0c527a6 tip
1994 commit top repo
1993 commit top repo
1995 branch: default
1994 branch: default
1996 commit: 1 subrepos
1995 commit: 1 subrepos
1997 update: (current)
1996 update: (current)
1998 $ hg ci -m "this commit should fail without -S"
1997 $ hg ci -m "this commit should fail without -S"
1999 abort: uncommitted changes in subrepo subrepo
1998 abort: uncommitted changes in subrepo subrepo
2000 (use --subrepos for recursive commit)
1999 (use --subrepos for recursive commit)
2001 [255]
2000 [255]
2002
2001
2003 Add a normal file to the subrepo, then test archiving
2002 Add a normal file to the subrepo, then test archiving
2004
2003
2005 $ echo 'normal file' > subrepo/normal.txt
2004 $ echo 'normal file' > subrepo/normal.txt
2006 $ hg -R subrepo add subrepo/normal.txt
2005 $ hg -R subrepo add subrepo/normal.txt
2007
2006
2008 Lock in subrepo, otherwise the change isn't archived
2007 Lock in subrepo, otherwise the change isn't archived
2009
2008
2010 $ hg ci -S -m "add normal file to top level"
2009 $ hg ci -S -m "add normal file to top level"
2011 committing subrepository subrepo
2010 committing subrepository subrepo
2012 Invoking status precommit hook
2011 Invoking status precommit hook
2013 M large.txt
2012 M large.txt
2014 A normal.txt
2013 A normal.txt
2015 Invoking status precommit hook
2014 Invoking status precommit hook
2016 M .hgsubstate
2015 M .hgsubstate
2017 $ hg archive -S ../lf_subrepo_archive
2016 $ hg archive -S ../lf_subrepo_archive
2018 $ find ../lf_subrepo_archive | sort
2017 $ find ../lf_subrepo_archive | sort
2019 ../lf_subrepo_archive
2018 ../lf_subrepo_archive
2020 ../lf_subrepo_archive/.hg_archival.txt
2019 ../lf_subrepo_archive/.hg_archival.txt
2021 ../lf_subrepo_archive/.hgsub
2020 ../lf_subrepo_archive/.hgsub
2022 ../lf_subrepo_archive/.hgsubstate
2021 ../lf_subrepo_archive/.hgsubstate
2023 ../lf_subrepo_archive/a
2022 ../lf_subrepo_archive/a
2024 ../lf_subrepo_archive/a/b
2023 ../lf_subrepo_archive/a/b
2025 ../lf_subrepo_archive/a/b/c
2024 ../lf_subrepo_archive/a/b/c
2026 ../lf_subrepo_archive/a/b/c/d
2025 ../lf_subrepo_archive/a/b/c/d
2027 ../lf_subrepo_archive/a/b/c/d/e.large.txt
2026 ../lf_subrepo_archive/a/b/c/d/e.large.txt
2028 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
2027 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
2029 ../lf_subrepo_archive/a/b/c/x
2028 ../lf_subrepo_archive/a/b/c/x
2030 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
2029 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
2031 ../lf_subrepo_archive/subrepo
2030 ../lf_subrepo_archive/subrepo
2032 ../lf_subrepo_archive/subrepo/large.txt
2031 ../lf_subrepo_archive/subrepo/large.txt
2033 ../lf_subrepo_archive/subrepo/normal.txt
2032 ../lf_subrepo_archive/subrepo/normal.txt
2034
2033
2035 Test update with subrepos.
2034 Test update with subrepos.
2036
2035
2037 $ hg update 0
2036 $ hg update 0
2038 getting changed largefiles
2037 getting changed largefiles
2039 0 largefiles updated, 1 removed
2038 0 largefiles updated, 1 removed
2040 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2039 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2041 $ hg status -S
2040 $ hg status -S
2042 $ hg update tip
2041 $ hg update tip
2043 getting changed largefiles
2042 getting changed largefiles
2044 1 largefiles updated, 0 removed
2043 1 largefiles updated, 0 removed
2045 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
2044 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
2046 $ hg status -S
2045 $ hg status -S
2047 # modify a large file
2046 # modify a large file
2048 $ echo "modified" > subrepo/large.txt
2047 $ echo "modified" > subrepo/large.txt
2049 $ hg st -S
2048 $ hg st -S
2050 M subrepo/large.txt
2049 M subrepo/large.txt
2051 # update -C should revert the change.
2050 # update -C should revert the change.
2052 $ hg update -C
2051 $ hg update -C
2053 getting changed largefiles
2052 getting changed largefiles
2054 1 largefiles updated, 0 removed
2053 1 largefiles updated, 0 removed
2055 getting changed largefiles
2054 getting changed largefiles
2056 0 largefiles updated, 0 removed
2055 0 largefiles updated, 0 removed
2057 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2056 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2058 $ hg status -S
2057 $ hg status -S
2059
2058
2060 Test archiving a revision that references a subrepo that is not yet
2059 Test archiving a revision that references a subrepo that is not yet
2061 cloned (see test-subrepo-recursion.t):
2060 cloned (see test-subrepo-recursion.t):
2062
2061
2063 $ hg clone -U . ../empty
2062 $ hg clone -U . ../empty
2064 $ cd ../empty
2063 $ cd ../empty
2065 $ hg archive --subrepos -r tip ../archive.tar.gz
2064 $ hg archive --subrepos -r tip ../archive.tar.gz
2066 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
2065 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
2067 $ cd ..
2066 $ cd ..
2068
2067
2069 Test that addremove picks up largefiles prior to the initial commit (issue3541)
2068 Test that addremove picks up largefiles prior to the initial commit (issue3541)
2070
2069
2071 $ hg init addrm2
2070 $ hg init addrm2
2072 $ cd addrm2
2071 $ cd addrm2
2073 $ touch large.dat
2072 $ touch large.dat
2074 $ touch large2.dat
2073 $ touch large2.dat
2075 $ touch normal
2074 $ touch normal
2076 $ hg add --large large.dat
2075 $ hg add --large large.dat
2077 $ hg addremove -v
2076 $ hg addremove -v
2078 adding large2.dat as a largefile
2077 adding large2.dat as a largefile
2079 adding normal
2078 adding normal
2080
2079
2081 Test that forgetting all largefiles reverts to islfilesrepo() == False
2080 Test that forgetting all largefiles reverts to islfilesrepo() == False
2082 (addremove will add *.dat as normal files now)
2081 (addremove will add *.dat as normal files now)
2083 $ hg forget large.dat
2082 $ hg forget large.dat
2084 $ hg forget large2.dat
2083 $ hg forget large2.dat
2085 $ hg addremove -v
2084 $ hg addremove -v
2086 adding large.dat
2085 adding large.dat
2087 adding large2.dat
2086 adding large2.dat
2088
2087
2089 Test commit's addremove option prior to the first commit
2088 Test commit's addremove option prior to the first commit
2090 $ hg forget large.dat
2089 $ hg forget large.dat
2091 $ hg forget large2.dat
2090 $ hg forget large2.dat
2092 $ hg add --large large.dat
2091 $ hg add --large large.dat
2093 $ hg ci -Am "commit"
2092 $ hg ci -Am "commit"
2094 adding large2.dat as a largefile
2093 adding large2.dat as a largefile
2095 Invoking status precommit hook
2094 Invoking status precommit hook
2096 A large.dat
2095 A large.dat
2097 A large2.dat
2096 A large2.dat
2098 A normal
2097 A normal
2099 $ find .hglf | sort
2098 $ find .hglf | sort
2100 .hglf
2099 .hglf
2101 .hglf/large.dat
2100 .hglf/large.dat
2102 .hglf/large2.dat
2101 .hglf/large2.dat
2103
2102
2104 Test actions on largefiles using relative paths from subdir
2103 Test actions on largefiles using relative paths from subdir
2105
2104
2106 $ mkdir sub
2105 $ mkdir sub
2107 $ cd sub
2106 $ cd sub
2108 $ echo anotherlarge > anotherlarge
2107 $ echo anotherlarge > anotherlarge
2109 $ hg add --large anotherlarge
2108 $ hg add --large anotherlarge
2110 $ hg st
2109 $ hg st
2111 A sub/anotherlarge
2110 A sub/anotherlarge
2112 $ hg st anotherlarge
2111 $ hg st anotherlarge
2113 A anotherlarge
2112 A anotherlarge
2114 $ hg commit -m anotherlarge anotherlarge
2113 $ hg commit -m anotherlarge anotherlarge
2115 Invoking status precommit hook
2114 Invoking status precommit hook
2116 A sub/anotherlarge
2115 A sub/anotherlarge
2117 $ hg log anotherlarge
2116 $ hg log anotherlarge
2118 changeset: 1:9627a577c5e9
2117 changeset: 1:9627a577c5e9
2119 tag: tip
2118 tag: tip
2120 user: test
2119 user: test
2121 date: Thu Jan 01 00:00:00 1970 +0000
2120 date: Thu Jan 01 00:00:00 1970 +0000
2122 summary: anotherlarge
2121 summary: anotherlarge
2123
2122
2124 $ echo more >> anotherlarge
2123 $ echo more >> anotherlarge
2125 $ hg st .
2124 $ hg st .
2126 M anotherlarge
2125 M anotherlarge
2127 $ hg cat anotherlarge
2126 $ hg cat anotherlarge
2128 anotherlarge
2127 anotherlarge
2129 $ hg revert anotherlarge
2128 $ hg revert anotherlarge
2130 $ hg st
2129 $ hg st
2131 ? sub/anotherlarge.orig
2130 ? sub/anotherlarge.orig
2132 $ cd ..
2131 $ cd ..
2133
2132
2134 $ cd ..
2133 $ cd ..
2135
2134
2136 issue3651: summary/outgoing with largefiles shows "no remote repo"
2135 issue3651: summary/outgoing with largefiles shows "no remote repo"
2137 unexpectedly
2136 unexpectedly
2138
2137
2139 $ mkdir issue3651
2138 $ mkdir issue3651
2140 $ cd issue3651
2139 $ cd issue3651
2141
2140
2142 $ hg init src
2141 $ hg init src
2143 $ echo a > src/a
2142 $ echo a > src/a
2144 $ hg -R src add --large src/a
2143 $ hg -R src add --large src/a
2145 $ hg -R src commit -m '#0'
2144 $ hg -R src commit -m '#0'
2146 Invoking status precommit hook
2145 Invoking status precommit hook
2147 A a
2146 A a
2148
2147
2149 check messages when no remote repository is specified:
2148 check messages when no remote repository is specified:
2150 "no remote repo" route for "hg outgoing --large" is not tested here,
2149 "no remote repo" route for "hg outgoing --large" is not tested here,
2151 because it can't be reproduced easily.
2150 because it can't be reproduced easily.
2152
2151
2153 $ hg init clone1
2152 $ hg init clone1
2154 $ hg -R clone1 -q pull src
2153 $ hg -R clone1 -q pull src
2155 $ hg -R clone1 -q update
2154 $ hg -R clone1 -q update
2156 $ hg -R clone1 paths | grep default
2155 $ hg -R clone1 paths | grep default
2157 [1]
2156 [1]
2158
2157
2159 $ hg -R clone1 summary --large
2158 $ hg -R clone1 summary --large
2160 parent: 0:fc0bd45326d3 tip
2159 parent: 0:fc0bd45326d3 tip
2161 #0
2160 #0
2162 branch: default
2161 branch: default
2163 commit: (clean)
2162 commit: (clean)
2164 update: (current)
2163 update: (current)
2165 largefiles: (no remote repo)
2164 largefiles: (no remote repo)
2166
2165
2167 check messages when there is no files to upload:
2166 check messages when there is no files to upload:
2168
2167
2169 $ hg -q clone src clone2
2168 $ hg -q clone src clone2
2170 $ hg -R clone2 paths | grep default
2169 $ hg -R clone2 paths | grep default
2171 default = $TESTTMP/issue3651/src (glob)
2170 default = $TESTTMP/issue3651/src (glob)
2172
2171
2173 $ hg -R clone2 summary --large
2172 $ hg -R clone2 summary --large
2174 parent: 0:fc0bd45326d3 tip
2173 parent: 0:fc0bd45326d3 tip
2175 #0
2174 #0
2176 branch: default
2175 branch: default
2177 commit: (clean)
2176 commit: (clean)
2178 update: (current)
2177 update: (current)
2179 searching for changes
2178 searching for changes
2180 largefiles: (no files to upload)
2179 largefiles: (no files to upload)
2181 $ hg -R clone2 outgoing --large
2180 $ hg -R clone2 outgoing --large
2182 comparing with $TESTTMP/issue3651/src (glob)
2181 comparing with $TESTTMP/issue3651/src (glob)
2183 searching for changes
2182 searching for changes
2184 no changes found
2183 no changes found
2185 searching for changes
2184 searching for changes
2186 largefiles: no files to upload
2185 largefiles: no files to upload
2187 [1]
2186 [1]
2188
2187
2189 check messages when there are files to upload:
2188 check messages when there are files to upload:
2190
2189
2191 $ echo b > clone2/b
2190 $ echo b > clone2/b
2192 $ hg -R clone2 add --large clone2/b
2191 $ hg -R clone2 add --large clone2/b
2193 $ hg -R clone2 commit -m '#1'
2192 $ hg -R clone2 commit -m '#1'
2194 Invoking status precommit hook
2193 Invoking status precommit hook
2195 A b
2194 A b
2196 $ hg -R clone2 summary --large
2195 $ hg -R clone2 summary --large
2197 parent: 1:1acbe71ce432 tip
2196 parent: 1:1acbe71ce432 tip
2198 #1
2197 #1
2199 branch: default
2198 branch: default
2200 commit: (clean)
2199 commit: (clean)
2201 update: (current)
2200 update: (current)
2202 searching for changes
2201 searching for changes
2203 largefiles: 1 to upload
2202 largefiles: 1 to upload
2204 $ hg -R clone2 outgoing --large
2203 $ hg -R clone2 outgoing --large
2205 comparing with $TESTTMP/issue3651/src (glob)
2204 comparing with $TESTTMP/issue3651/src (glob)
2206 searching for changes
2205 searching for changes
2207 changeset: 1:1acbe71ce432
2206 changeset: 1:1acbe71ce432
2208 tag: tip
2207 tag: tip
2209 user: test
2208 user: test
2210 date: Thu Jan 01 00:00:00 1970 +0000
2209 date: Thu Jan 01 00:00:00 1970 +0000
2211 summary: #1
2210 summary: #1
2212
2211
2213 searching for changes
2212 searching for changes
2214 largefiles to upload:
2213 largefiles to upload:
2215 b
2214 b
2216
2215
2217
2216
2218 $ cd ..
2217 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now