##// END OF EJS Templates
convert/mtn: Fix conversion of large files from mtn (broken in ed97955e0c04)...
Daniel Atallah -
r13792:a916e8de default
parent child Browse files
Show More
@@ -1,358 +1,358 b''
1 1 # monotone.py - monotone support for the convert extension
2 2 #
3 3 # Copyright 2008, 2009 Mikkel Fahnoe Jorgensen <mikkel@dvide.com> and
4 4 # others
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 import os, re
10 10 from mercurial import util
11 11 from common import NoRepo, commit, converter_source, checktool
12 12 from common import commandline
13 13 from mercurial.i18n import _
14 14
15 15 class monotone_source(converter_source, commandline):
16 16 def __init__(self, ui, path=None, rev=None):
17 17 converter_source.__init__(self, ui, path, rev)
18 18 commandline.__init__(self, ui, 'mtn')
19 19
20 20 self.ui = ui
21 21 self.path = path
22 22 self.automatestdio = False
23 23 self.rev = rev
24 24
25 25 norepo = NoRepo(_("%s does not look like a monotone repository")
26 26 % path)
27 27 if not os.path.exists(os.path.join(path, '_MTN')):
28 28 # Could be a monotone repository (SQLite db file)
29 29 try:
30 30 header = file(path, 'rb').read(16)
31 31 except:
32 32 header = ''
33 33 if header != 'SQLite format 3\x00':
34 34 raise norepo
35 35
36 36 # regular expressions for parsing monotone output
37 37 space = r'\s*'
38 38 name = r'\s+"((?:\\"|[^"])*)"\s*'
39 39 value = name
40 40 revision = r'\s+\[(\w+)\]\s*'
41 41 lines = r'(?:.|\n)+'
42 42
43 43 self.dir_re = re.compile(space + "dir" + name)
44 44 self.file_re = re.compile(space + "file" + name +
45 45 "content" + revision)
46 46 self.add_file_re = re.compile(space + "add_file" + name +
47 47 "content" + revision)
48 48 self.patch_re = re.compile(space + "patch" + name +
49 49 "from" + revision + "to" + revision)
50 50 self.rename_re = re.compile(space + "rename" + name + "to" + name)
51 51 self.delete_re = re.compile(space + "delete" + name)
52 52 self.tag_re = re.compile(space + "tag" + name + "revision" +
53 53 revision)
54 54 self.cert_re = re.compile(lines + space + "name" + name +
55 55 "value" + value)
56 56
57 57 attr = space + "file" + lines + space + "attr" + space
58 58 self.attr_execute_re = re.compile(attr + '"mtn:execute"' +
59 59 space + '"true"')
60 60
61 61 # cached data
62 62 self.manifest_rev = None
63 63 self.manifest = None
64 64 self.files = None
65 65 self.dirs = None
66 66
67 67 checktool('mtn', abort=False)
68 68
69 69 def mtnrun(self, *args, **kwargs):
70 70 if self.automatestdio:
71 71 return self.mtnrunstdio(*args, **kwargs)
72 72 else:
73 73 return self.mtnrunsingle(*args, **kwargs)
74 74
75 75 def mtnrunsingle(self, *args, **kwargs):
76 76 kwargs['d'] = self.path
77 77 return self.run0('automate', *args, **kwargs)
78 78
79 79 def mtnrunstdio(self, *args, **kwargs):
80 80 # Prepare the command in automate stdio format
81 81 command = []
82 82 for k, v in kwargs.iteritems():
83 83 command.append("%s:%s" % (len(k), k))
84 84 if v:
85 85 command.append("%s:%s" % (len(v), v))
86 86 if command:
87 87 command.insert(0, 'o')
88 88 command.append('e')
89 89
90 90 command.append('l')
91 91 for arg in args:
92 92 command += "%s:%s" % (len(arg), arg)
93 93 command.append('e')
94 94 command = ''.join(command)
95 95
96 96 self.ui.debug("mtn: sending '%s'\n" % command)
97 97 self.mtnwritefp.write(command)
98 98 self.mtnwritefp.flush()
99 99
100 100 return self.mtnstdioreadcommandoutput(command)
101 101
102 102 def mtnstdioreadpacket(self):
103 103 read = None
104 104 commandnbr = ''
105 105 while read != ':':
106 106 read = self.mtnreadfp.read(1)
107 107 if not read:
108 108 raise util.Abort(_('bad mtn packet - no end of commandnbr'))
109 109 commandnbr += read
110 110 commandnbr = commandnbr[:-1]
111 111
112 112 stream = self.mtnreadfp.read(1)
113 113 if stream not in 'mewptl':
114 114 raise util.Abort(_('bad mtn packet - bad stream type %s' % stream))
115 115
116 116 read = self.mtnreadfp.read(1)
117 117 if read != ':':
118 118 raise util.Abort(_('bad mtn packet - no divider before size'))
119 119
120 120 read = None
121 121 lengthstr = ''
122 122 while read != ':':
123 123 read = self.mtnreadfp.read(1)
124 124 if not read:
125 125 raise util.Abort(_('bad mtn packet - no end of packet size'))
126 126 lengthstr += read
127 127 try:
128 128 length = long(lengthstr[:-1])
129 129 except TypeError:
130 130 raise util.Abort(_('bad mtn packet - bad packet size %s')
131 131 % lengthstr)
132 132
133 133 read = self.mtnreadfp.read(length)
134 134 if len(read) != length:
135 135 raise util.Abort(_("bad mtn packet - unable to read full packet "
136 136 "read %s of %s") % (len(read), length))
137 137
138 138 return (commandnbr, stream, length, read)
139 139
140 140 def mtnstdioreadcommandoutput(self, command):
141 retval = ''
141 retval = []
142 142 while True:
143 143 commandnbr, stream, length, output = self.mtnstdioreadpacket()
144 144 self.ui.debug('mtn: read packet %s:%s:%s\n' %
145 145 (commandnbr, stream, length))
146 146
147 147 if stream == 'l':
148 148 # End of command
149 149 if output != '0':
150 150 raise util.Abort(_("mtn command '%s' returned %s") %
151 151 (command, output))
152 152 break
153 153 elif stream in 'ew':
154 154 # Error, warning output
155 155 self.ui.warn(_('%s error:\n') % self.command)
156 156 self.ui.warn(output)
157 157 elif stream == 'p':
158 158 # Progress messages
159 159 self.ui.debug('mtn: ' + output)
160 160 elif stream == 'm':
161 161 # Main stream - command output
162 retval = output
162 retval.append(output)
163 163
164 return retval
164 return ''.join(retval)
165 165
166 166 def mtnloadmanifest(self, rev):
167 167 if self.manifest_rev == rev:
168 168 return
169 169 self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n")
170 170 self.manifest_rev = rev
171 171 self.files = {}
172 172 self.dirs = {}
173 173
174 174 for e in self.manifest:
175 175 m = self.file_re.match(e)
176 176 if m:
177 177 attr = ""
178 178 name = m.group(1)
179 179 node = m.group(2)
180 180 if self.attr_execute_re.match(e):
181 181 attr += "x"
182 182 self.files[name] = (node, attr)
183 183 m = self.dir_re.match(e)
184 184 if m:
185 185 self.dirs[m.group(1)] = True
186 186
187 187 def mtnisfile(self, name, rev):
188 188 # a non-file could be a directory or a deleted or renamed file
189 189 self.mtnloadmanifest(rev)
190 190 return name in self.files
191 191
192 192 def mtnisdir(self, name, rev):
193 193 self.mtnloadmanifest(rev)
194 194 return name in self.dirs
195 195
196 196 def mtngetcerts(self, rev):
197 197 certs = {"author":"<missing>", "date":"<missing>",
198 198 "changelog":"<missing>", "branch":"<missing>"}
199 199 certlist = self.mtnrun("certs", rev)
200 200 # mtn < 0.45:
201 201 # key "test@selenic.com"
202 202 # mtn >= 0.45:
203 203 # key [ff58a7ffb771907c4ff68995eada1c4da068d328]
204 204 certlist = re.split('\n\n key ["\[]', certlist)
205 205 for e in certlist:
206 206 m = self.cert_re.match(e)
207 207 if m:
208 208 name, value = m.groups()
209 209 value = value.replace(r'\"', '"')
210 210 value = value.replace(r'\\', '\\')
211 211 certs[name] = value
212 212 # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306
213 213 # and all times are stored in UTC
214 214 certs["date"] = certs["date"].split('.')[0] + " UTC"
215 215 return certs
216 216
217 217 # implement the converter_source interface:
218 218
219 219 def getheads(self):
220 220 if not self.rev:
221 221 return self.mtnrun("leaves").splitlines()
222 222 else:
223 223 return [self.rev]
224 224
225 225 def getchanges(self, rev):
226 226 #revision = self.mtncmd("get_revision %s" % rev).split("\n\n")
227 227 revision = self.mtnrun("get_revision", rev).split("\n\n")
228 228 files = {}
229 229 ignoremove = {}
230 230 renameddirs = []
231 231 copies = {}
232 232 for e in revision:
233 233 m = self.add_file_re.match(e)
234 234 if m:
235 235 files[m.group(1)] = rev
236 236 ignoremove[m.group(1)] = rev
237 237 m = self.patch_re.match(e)
238 238 if m:
239 239 files[m.group(1)] = rev
240 240 # Delete/rename is handled later when the convert engine
241 241 # discovers an IOError exception from getfile,
242 242 # but only if we add the "from" file to the list of changes.
243 243 m = self.delete_re.match(e)
244 244 if m:
245 245 files[m.group(1)] = rev
246 246 m = self.rename_re.match(e)
247 247 if m:
248 248 toname = m.group(2)
249 249 fromname = m.group(1)
250 250 if self.mtnisfile(toname, rev):
251 251 ignoremove[toname] = 1
252 252 copies[toname] = fromname
253 253 files[toname] = rev
254 254 files[fromname] = rev
255 255 elif self.mtnisdir(toname, rev):
256 256 renameddirs.append((fromname, toname))
257 257
258 258 # Directory renames can be handled only once we have recorded
259 259 # all new files
260 260 for fromdir, todir in renameddirs:
261 261 renamed = {}
262 262 for tofile in self.files:
263 263 if tofile in ignoremove:
264 264 continue
265 265 if tofile.startswith(todir + '/'):
266 266 renamed[tofile] = fromdir + tofile[len(todir):]
267 267 # Avoid chained moves like:
268 268 # d1(/a) => d3/d1(/a)
269 269 # d2 => d3
270 270 ignoremove[tofile] = 1
271 271 for tofile, fromfile in renamed.items():
272 272 self.ui.debug (_("copying file in renamed directory "
273 273 "from '%s' to '%s'")
274 274 % (fromfile, tofile), '\n')
275 275 files[tofile] = rev
276 276 copies[tofile] = fromfile
277 277 for fromfile in renamed.values():
278 278 files[fromfile] = rev
279 279
280 280 return (files.items(), copies)
281 281
282 282 def getfile(self, name, rev):
283 283 if not self.mtnisfile(name, rev):
284 284 raise IOError() # file was deleted or renamed
285 285 try:
286 286 data = self.mtnrun("get_file_of", name, r=rev)
287 287 except:
288 288 raise IOError() # file was deleted or renamed
289 289 self.mtnloadmanifest(rev)
290 290 node, attr = self.files.get(name, (None, ""))
291 291 return data, attr
292 292
293 293 def getcommit(self, rev):
294 294 extra = {}
295 295 certs = self.mtngetcerts(rev)
296 296 if certs.get('suspend') == certs["branch"]:
297 297 extra['close'] = '1'
298 298 return commit(
299 299 author=certs["author"],
300 300 date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")),
301 301 desc=certs["changelog"],
302 302 rev=rev,
303 303 parents=self.mtnrun("parents", rev).splitlines(),
304 304 branch=certs["branch"],
305 305 extra=extra)
306 306
307 307 def gettags(self):
308 308 tags = {}
309 309 for e in self.mtnrun("tags").split("\n\n"):
310 310 m = self.tag_re.match(e)
311 311 if m:
312 312 tags[m.group(1)] = m.group(2)
313 313 return tags
314 314
315 315 def getchangedfiles(self, rev, i):
316 316 # This function is only needed to support --filemap
317 317 # ... and we don't support that
318 318 raise NotImplementedError()
319 319
320 320 def before(self):
321 321 # Check if we have a new enough version to use automate stdio
322 322 version = 0.0
323 323 try:
324 324 versionstr = self.mtnrunsingle("interface_version")
325 325 version = float(versionstr)
326 326 except Exception:
327 327 raise util.Abort(_("unable to determine mtn automate interface "
328 328 "version"))
329 329
330 330 if version >= 12.0:
331 331 self.automatestdio = True
332 332 self.ui.debug("mtn automate version %s - using automate stdio\n" %
333 333 version)
334 334
335 335 # launch the long-running automate stdio process
336 336 self.mtnwritefp, self.mtnreadfp = self._run2('automate', 'stdio',
337 337 '-d', self.path)
338 338 # read the headers
339 339 read = self.mtnreadfp.readline()
340 340 if read != 'format-version: 2\n':
341 341 raise util.Abort(_('mtn automate stdio header unexpected: %s')
342 342 % read)
343 343 while read != '\n':
344 344 read = self.mtnreadfp.readline()
345 345 if not read:
346 346 raise util.Abort(_("failed to reach end of mtn automate "
347 347 "stdio headers"))
348 348 else:
349 349 self.ui.debug("mtn automate version %s - not using automate stdio "
350 350 "(automate >= 12.0 - mtn >= 0.46 is needed)\n" % version)
351 351
352 352 def after(self):
353 353 if self.automatestdio:
354 354 self.mtnwritefp.close()
355 355 self.mtnwritefp = None
356 356 self.mtnreadfp.close()
357 357 self.mtnreadfp = None
358 358
@@ -1,368 +1,388 b''
1 1
2 2 $ "$TESTDIR/hghave" mtn || exit 80
3 3
4 4 Monotone directory is called .monotone on *nix and monotone
5 5 on Windows. Having a variable here ease test patching.
6 6
7 7 $ mtndir=.monotone
8 8 $ echo "[extensions]" >> $HGRCPATH
9 9 $ echo "convert=" >> $HGRCPATH
10 10 $ echo 'graphlog =' >> $HGRCPATH
11 11
12 12 Windows version of monotone home
13 13
14 14 $ APPDATA=$HOME; export APPDATA
15 15
16 16 tedious monotone keys configuration
17 17 The /dev/null redirection is necessary under Windows, or
18 18 it complains about home directory permissions
19 19
20 20 $ mtn --quiet genkey test@selenic.com 1>/dev/null 2>&1 <<EOF
21 21 > passphrase
22 22 > passphrase
23 23 > EOF
24 24 $ cat >> $HOME/$mtndir/monotonerc <<EOF
25 25 > function get_passphrase(keypair_id)
26 26 > return "passphrase"
27 27 > end
28 28 > EOF
29 29
30 30 create monotone repository
31 31
32 32 $ mtn db init --db=repo.mtn
33 33 $ mtn --db=repo.mtn --branch=com.selenic.test setup workingdir
34 34 $ cd workingdir
35 35 $ echo a > a
36 36 $ mkdir dir
37 37 $ echo b > dir/b
38 38 $ echo d > dir/d
39 39 $ python -c 'file("bin", "wb").write("a\\x00b")'
40 40 $ echo c > c
41 41 $ mtn add a dir/b dir/d c bin
42 42 mtn: adding a to workspace manifest
43 43 mtn: adding bin to workspace manifest
44 44 mtn: adding c to workspace manifest
45 45 mtn: adding dir to workspace manifest
46 46 mtn: adding dir/b to workspace manifest
47 47 mtn: adding dir/d to workspace manifest
48 48 $ mtn ci -m initialize
49 49 mtn: beginning commit on branch 'com.selenic.test'
50 50 mtn: committed revision 0f6e5e4f2e7d2a8ef312408f57618abf026afd90
51 51
52 52 update monotone working directory
53 53
54 54 $ mtn mv a dir/a
55 55 mtn: skipping dir, already accounted for in workspace
56 56 mtn: renaming a to dir/a in workspace manifest
57 57 $ echo a >> dir/a
58 58 $ echo b >> dir/b
59 59 $ mtn drop c
60 60 mtn: dropping c from workspace manifest
61 61 $ python -c 'file("bin", "wb").write("b\\x00c")'
62 62 $ mtn ci -m update1
63 63 mtn: beginning commit on branch 'com.selenic.test'
64 64 mtn: committed revision 51d0a982464573a2a2cf5ee2c9219c652aaebeff
65 65 $ cd ..
66 66
67 67 convert once
68 68
69 69 $ hg convert -s mtn repo.mtn
70 70 assuming destination repo.mtn-hg
71 71 initializing destination repo.mtn-hg repository
72 72 scanning source...
73 73 sorting...
74 74 converting...
75 75 1 initialize
76 76 0 update1
77 77 $ cd workingdir
78 78 $ echo e > e
79 79 $ mtn add e
80 80 mtn: adding e to workspace manifest
81 81 $ mtn drop dir/b
82 82 mtn: dropping dir/b from workspace manifest
83 83 $ mtn mv bin bin2
84 84 mtn: renaming bin to bin2 in workspace manifest
85 85 $ mtn ci -m 'update2 "with" quotes'
86 86 mtn: beginning commit on branch 'com.selenic.test'
87 87 mtn: committed revision ebe58335d85d8cb176b6d0a12be04f5314b998da
88 88
89 89 test directory move
90 90
91 91 $ mkdir -p dir1/subdir1
92 92 $ mkdir -p dir1/subdir2_other
93 93 $ echo file1 > dir1/subdir1/file1
94 94 $ echo file2 > dir1/subdir2_other/file1
95 95 $ mtn add dir1/subdir1/file1 dir1/subdir2_other/file1
96 96 mtn: adding dir1 to workspace manifest
97 97 mtn: adding dir1/subdir1 to workspace manifest
98 98 mtn: adding dir1/subdir1/file1 to workspace manifest
99 99 mtn: adding dir1/subdir2_other to workspace manifest
100 100 mtn: adding dir1/subdir2_other/file1 to workspace manifest
101 101 $ mtn ci -m createdir1
102 102 mtn: beginning commit on branch 'com.selenic.test'
103 103 mtn: committed revision a8d62bc04fee4d2936d28e98bbcc81686dd74306
104 104 $ mtn rename dir1/subdir1 dir1/subdir2
105 105 mtn: skipping dir1, already accounted for in workspace
106 106 mtn: renaming dir1/subdir1 to dir1/subdir2 in workspace manifest
107 107 $ mtn ci -m movedir1
108 108 mtn: beginning commit on branch 'com.selenic.test'
109 109 mtn: committed revision 2c3d241bbbfe538b1b51d910f5676407e3f4d3a6
110 110
111 111 test subdirectory move
112 112
113 113 $ mtn mv dir dir2
114 114 mtn: renaming dir to dir2 in workspace manifest
115 115 $ echo newfile > dir2/newfile
116 116 $ mtn drop dir2/d
117 117 mtn: dropping dir2/d from workspace manifest
118 118 $ mtn add dir2/newfile
119 119 mtn: adding dir2/newfile to workspace manifest
120 120 $ mtn ci -m movedir
121 121 mtn: beginning commit on branch 'com.selenic.test'
122 122 mtn: committed revision fdb5a02dae8bfce3a79b3393680af471016e1b4c
123 123
124 124 Test directory removal with empty directory
125 125
126 126 $ mkdir dir2/dir
127 127 $ mkdir dir2/dir/subdir
128 128 $ echo f > dir2/dir/subdir/f
129 129 $ mkdir dir2/dir/emptydir
130 130 $ mtn add --quiet -R dir2/dir
131 131 $ mtn ci -m emptydir
132 132 mtn: beginning commit on branch 'com.selenic.test'
133 133 mtn: committed revision 8bbf76d717001d24964e4604739fdcd0f539fc88
134 134 $ mtn drop -R dir2/dir
135 135 mtn: dropping dir2/dir/subdir/f from workspace manifest
136 136 mtn: dropping dir2/dir/subdir from workspace manifest
137 137 mtn: dropping dir2/dir/emptydir from workspace manifest
138 138 mtn: dropping dir2/dir from workspace manifest
139 139 $ mtn ci -m dropdirectory
140 140 mtn: beginning commit on branch 'com.selenic.test'
141 141 mtn: committed revision 2323d4bc324e6c82628dc04d47a9fd32ad24e322
142 142
143 143 test directory and file move
144 144
145 145 $ mkdir -p dir3/d1
146 146 $ echo a > dir3/a
147 147 $ mtn add dir3/a dir3/d1
148 148 mtn: adding dir3 to workspace manifest
149 149 mtn: adding dir3/a to workspace manifest
150 150 mtn: adding dir3/d1 to workspace manifest
151 151 $ mtn ci -m dirfilemove
152 152 mtn: beginning commit on branch 'com.selenic.test'
153 153 mtn: committed revision 47b192f720faa622f48c68d1eb075b26d405aa8b
154 154 $ mtn mv dir3/a dir3/d1/a
155 155 mtn: skipping dir3/d1, already accounted for in workspace
156 156 mtn: renaming dir3/a to dir3/d1/a in workspace manifest
157 157 $ mtn mv dir3/d1 dir3/d2
158 158 mtn: skipping dir3, already accounted for in workspace
159 159 mtn: renaming dir3/d1 to dir3/d2 in workspace manifest
160 160 $ mtn ci -m dirfilemove2
161 161 mtn: beginning commit on branch 'com.selenic.test'
162 162 mtn: committed revision 8b543a400d3ee7f6d4bb1835b9b9e3747c8cb632
163 163
164 164 test directory move into another directory move
165 165
166 166 $ mkdir dir4
167 167 $ mkdir dir5
168 168 $ echo a > dir4/a
169 169 $ mtn add dir4/a dir5
170 170 mtn: adding dir4 to workspace manifest
171 171 mtn: adding dir4/a to workspace manifest
172 172 mtn: adding dir5 to workspace manifest
173 173 $ mtn ci -m dirdirmove
174 174 mtn: beginning commit on branch 'com.selenic.test'
175 175 mtn: committed revision 466e0b2afc7a55aa2b4ab2f57cb240bb6cd66fc7
176 176 $ mtn mv dir5 dir6
177 177 mtn: renaming dir5 to dir6 in workspace manifest
178 178 $ mtn mv dir4 dir6/dir4
179 179 mtn: skipping dir6, already accounted for in workspace
180 180 mtn: renaming dir4 to dir6/dir4 in workspace manifest
181 181 $ mtn ci -m dirdirmove2
182 182 mtn: beginning commit on branch 'com.selenic.test'
183 183 mtn: committed revision 3d1f77ebad0c23a5d14911be3b670f990991b749
184 184
185 185 test diverging directory moves
186 186
187 187 $ mkdir -p dir7/dir9/dir8
188 188 $ echo a > dir7/dir9/dir8/a
189 189 $ echo b > dir7/dir9/b
190 190 $ echo c > dir7/c
191 191 $ mtn add -R dir7
192 192 mtn: adding dir7 to workspace manifest
193 193 mtn: adding dir7/c to workspace manifest
194 194 mtn: adding dir7/dir9 to workspace manifest
195 195 mtn: adding dir7/dir9/b to workspace manifest
196 196 mtn: adding dir7/dir9/dir8 to workspace manifest
197 197 mtn: adding dir7/dir9/dir8/a to workspace manifest
198 198 $ mtn ci -m divergentdirmove
199 199 mtn: beginning commit on branch 'com.selenic.test'
200 200 mtn: committed revision 08a08511f18b428d840199b062de90d0396bc2ed
201 201 $ mtn mv dir7 dir7-2
202 202 mtn: renaming dir7 to dir7-2 in workspace manifest
203 203 $ mtn mv dir7-2/dir9 dir9-2
204 204 mtn: renaming dir7-2/dir9 to dir9-2 in workspace manifest
205 205 $ mtn mv dir9-2/dir8 dir8-2
206 206 mtn: renaming dir9-2/dir8 to dir8-2 in workspace manifest
207 207 $ mtn ci -m divergentdirmove2
208 208 mtn: beginning commit on branch 'com.selenic.test'
209 209 mtn: committed revision 4a736634505795f17786fffdf2c9cbf5b11df6f6
210 210
211 test large file support (> 32kB)
212
213 $ python -c 'for x in range(10000): print x' > large-file
214 $ $TESTDIR/md5sum.py large-file
215 5d6de8a95c3b6bf9e0ffb808ba5299c1 large-file
216 $ mtn add large-file
217 mtn: adding large-file to workspace manifest
218 $ mtn ci -m largefile
219 mtn: beginning commit on branch 'com.selenic.test'
220 mtn: committed revision f0a20fecd10dc4392d18fe69a03f1f4919d3387b
221
211 222 test suspending (closing a branch)
212 223
213 $ mtn suspend 4a736634505795f17786fffdf2c9cbf5b11df6f6 2> /dev/null
224 $ mtn suspend f0a20fecd10dc4392d18fe69a03f1f4919d3387b 2> /dev/null
214 225 $ cd ..
215 226
216 227 convert incrementally
217 228
218 229 $ hg convert -s mtn repo.mtn
219 230 assuming destination repo.mtn-hg
220 231 scanning source...
221 232 sorting...
222 233 converting...
223 11 update2 "with" quotes
224 10 createdir1
225 9 movedir1
226 8 movedir
227 7 emptydir
228 6 dropdirectory
229 5 dirfilemove
230 4 dirfilemove2
231 3 dirdirmove
232 2 dirdirmove2
233 1 divergentdirmove
234 0 divergentdirmove2
234 12 update2 "with" quotes
235 11 createdir1
236 10 movedir1
237 9 movedir
238 8 emptydir
239 7 dropdirectory
240 6 dirfilemove
241 5 dirfilemove2
242 4 dirdirmove
243 3 dirdirmove2
244 2 divergentdirmove
245 1 divergentdirmove2
246 0 largefile
235 247 $ glog()
236 248 > {
237 249 > hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
238 250 > }
239 251 $ cd repo.mtn-hg
240 252 $ hg up -C
241 11 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 12 files updated, 0 files merged, 0 files removed, 0 files unresolved
242 254 $ glog
243 @ 13 "divergentdirmove2" files: dir7-2/c dir7/c dir7/dir9/b dir7/dir9/dir8/a dir8-2/a dir9-2/b
255 @ 14 "largefile" files: large-file
256 |
257 o 13 "divergentdirmove2" files: dir7-2/c dir7/c dir7/dir9/b dir7/dir9/dir8/a dir8-2/a dir9-2/b
244 258 |
245 259 o 12 "divergentdirmove" files: dir7/c dir7/dir9/b dir7/dir9/dir8/a
246 260 |
247 261 o 11 "dirdirmove2" files: dir4/a dir6/dir4/a
248 262 |
249 263 o 10 "dirdirmove" files: dir4/a
250 264 |
251 265 o 9 "dirfilemove2" files: dir3/a dir3/d2/a
252 266 |
253 267 o 8 "dirfilemove" files: dir3/a
254 268 |
255 269 o 7 "dropdirectory" files: dir2/dir/subdir/f
256 270 |
257 271 o 6 "emptydir" files: dir2/dir/subdir/f
258 272 |
259 273 o 5 "movedir" files: dir/a dir/d dir2/a dir2/newfile
260 274 |
261 275 o 4 "movedir1" files: dir1/subdir1/file1 dir1/subdir2/file1
262 276 |
263 277 o 3 "createdir1" files: dir1/subdir1/file1 dir1/subdir2_other/file1
264 278 |
265 279 o 2 "update2 "with" quotes" files: bin bin2 dir/b e
266 280 |
267 281 o 1 "update1" files: a bin c dir/a dir/b
268 282 |
269 283 o 0 "initialize" files: a bin c dir/b dir/d
270 284
271 285
272 286 manifest
273 287
274 288 $ hg manifest
275 289 bin2
276 290 dir1/subdir2/file1
277 291 dir1/subdir2_other/file1
278 292 dir2/a
279 293 dir2/newfile
280 294 dir3/d2/a
281 295 dir6/dir4/a
282 296 dir7-2/c
283 297 dir8-2/a
284 298 dir9-2/b
285 299 e
300 large-file
286 301
287 302 contents
288 303
289 304 $ cat dir2/a
290 305 a
291 306 a
292 307 $ test -d dir2/dir && echo 'removed dir2/dir is still there!'
293 308 [1]
294 309
295 310 file move
296 311
297 312 $ hg log -v -C -r 1 | grep copies
298 313 copies: dir/a (a)
299 314
300 315 check directory move
301 316
302 317 $ hg manifest -r 4
303 318 bin2
304 319 dir/a
305 320 dir/d
306 321 dir1/subdir2/file1
307 322 dir1/subdir2_other/file1
308 323 e
309 324 $ test -d dir1/subdir2 || echo 'new dir1/subdir2 does not exist!'
310 325 $ test -d dir1/subdir1 && echo 'renamed dir1/subdir1 is still there!'
311 326 [1]
312 327 $ hg log -v -C -r 4 | grep copies
313 328 copies: dir1/subdir2/file1 (dir1/subdir1/file1)
314 329
315 330 check file remove with directory move
316 331
317 332 $ hg manifest -r 5
318 333 bin2
319 334 dir1/subdir2/file1
320 335 dir1/subdir2_other/file1
321 336 dir2/a
322 337 dir2/newfile
323 338 e
324 339
325 340 check file move with directory move
326 341
327 342 $ hg manifest -r 9
328 343 bin2
329 344 dir1/subdir2/file1
330 345 dir1/subdir2_other/file1
331 346 dir2/a
332 347 dir2/newfile
333 348 dir3/d2/a
334 349 e
335 350
336 351 check file directory directory move
337 352
338 353 $ hg manifest -r 11
339 354 bin2
340 355 dir1/subdir2/file1
341 356 dir1/subdir2_other/file1
342 357 dir2/a
343 358 dir2/newfile
344 359 dir3/d2/a
345 360 dir6/dir4/a
346 361 e
347 362
348 363 check divergent directory moves
349 364
350 365 $ hg manifest -r 13
351 366 bin2
352 367 dir1/subdir2/file1
353 368 dir1/subdir2_other/file1
354 369 dir2/a
355 370 dir2/newfile
356 371 dir3/d2/a
357 372 dir6/dir4/a
358 373 dir7-2/c
359 374 dir8-2/a
360 375 dir9-2/b
361 376 e
362 377
378 test large file support (> 32kB)
379
380 $ $TESTDIR/md5sum.py large-file
381 5d6de8a95c3b6bf9e0ffb808ba5299c1 large-file
382
363 383 check branch closing
364 384
365 385 $ hg branches -a
366 386 $ hg branches -c
367 com.selenic.test 13:* (closed) (glob)
387 com.selenic.test 14:* (closed) (glob)
368 388
General Comments 0
You need to be logged in to leave comments. Login now