def check(self): compathacks.progress(self.ui, 'verify', None, total=self.total) for f in self.unexpected: self.ui.write('unexpected file: %s\n' % f) self.failed = True for f in self.missing: self.ui.write('missing file: %s\n' % f) self.failed = True return not self.failed
def add_file(self, path, parent_baton=None, copyfrom_path=None, copyfrom_revision=None, file_pool=None): if path in self.unexpected: self.unexpected.remove(path) self.file = path self.props = {} else: self.total += 1 self.missing.add(path) self.failed = True self.file = None self.props = None self.seen += 1 compathacks.progress(self.ui, 'verify', self.seen, total=self.total)
def pull(repo, source, heads=[], force=False, meta=None): """pull new revisions from Subversion""" assert source.capable('subversion') svn_url = source.svnurl # Split off #rev svn_url, heads, checkout = util.parseurl(svn_url, heads) old_encoding = util.swap_out_encoding() total = None try: have_replay = not repo.ui.configbool('hgsubversion', 'stupid') if not have_replay: repo.ui.note('fetching stupidly...\n') svn = source.svn if meta is None: meta = repo.svnmeta(svn.uuid, svn.subdir) stopat_rev = util.parse_revnum(svn, checkout) if meta.layout == 'auto': meta.layout = meta.layout_from_subversion(svn, (stopat_rev or None)) repo.ui.note('using %s layout\n' % meta.layout) if meta.branch: if meta.layout != 'single': msg = ('branch cannot be specified for Subversion clones using ' 'standard directory layout') raise hgerror.Abort(msg) meta.branchmap['default'] = meta.branch ui = repo.ui start = meta.revmap.lastpulled if start <= 0: # we are initializing a new repository start = util.parse_revnum(svn, repo.ui.config('hgsubversion', 'startrev', 0)) if start > 0: if meta.layout == 'standard': raise hgerror.Abort('non-zero start revisions are only ' 'supported for single-directory clones.') ui.note('starting at revision %d; any prior will be ignored\n' % start) # fetch all revisions *including* the one specified... start -= 1 # anything less than zero makes no sense if start < 0: start = 0 skiprevs = repo.ui.configlist('hgsubversion', 'unsafeskip', '') skiprevs = set(util.parse_revnum(svn, r) for r in skiprevs) oldrevisions = len(meta.revmap) if stopat_rev: total = stopat_rev - start else: total = svn.HEAD - start lastpulled = None lock = meta.repo.lock() try: # start converting revisions firstrun = True for r in svn.revisions(start=start, stop=stopat_rev): if (r.revnum in skiprevs or (r.author is None and r.message == 'This is an empty revision for padding.')): lastpulled = r.revnum continue tbdelta = meta.update_branch_tag_map_for_rev(r) # got a 502? Try more than once! tries = 0 converted = False while not converted: try: msg = meta.getmessage(r).strip() if msg: msg = [s.strip() for s in msg.splitlines() if s][0] if getattr(ui, 'termwidth', False): w = ui.termwidth() else: w = hgutil.termwidth() bits = (r.revnum, r.author, msg) ui.status(('[r%d] %s: %s' % bits)[:w] + '\n') compathacks.progress(ui, 'pull', r.revnum - start, total=total) meta.save_tbdelta(tbdelta) close = pullfuns[have_replay](ui, meta, svn, r, tbdelta, firstrun) meta.committags(r, close) for branch, parent in close.iteritems(): if parent in (None, node.nullid): continue meta.delbranch(branch, parent, r) meta.save() converted = True firstrun = False except svnwrap.SubversionRepoCanNotReplay, e: # pragma: no cover ui.status('%s\n' % e.message) stupidmod.print_your_svn_is_old_message(ui) have_replay = False except svnwrap.SubversionException, e: # pragma: no cover if (e.args[1] == svnwrap.ERR_RA_DAV_REQUEST_FAILED and '502' in str(e) and tries < 3): tries += 1 ui.status('Got a 502, retrying (%s)\n' % tries) else: ui.traceback() raise hgerror.Abort(*e.args)
and tries < 3): tries += 1 ui.status('Got a 502, retrying (%s)\n' % tries) else: ui.traceback() raise hgerror.Abort(*e.args) lastpulled = r.revnum except KeyboardInterrupt: ui.traceback() finally: lock.release() finally: if total is not None: compathacks.progress(ui, 'pull', None, total=total) util.swap_out_encoding(old_encoding) if lastpulled is not None: meta.revmap.lastpulled = lastpulled revisions = len(meta.revmap) - oldrevisions if revisions == 0: ui.status(i18n._("no changes found\n")) return 0 else: ui.status("pulled %d revisions\n" % revisions) def exchangepull(orig, repo, remote, heads=None, force=False, bookmarks=(), **kwargs): capable = getattr(remote, 'capable', lambda x: False)
def verify(ui, repo, args=None, **opts): '''verify current revision against Subversion repository ''' if repo is None: raise error.RepoError("There is no Mercurial repository" " here (.hg not found)") ctx = repo[opts.get('rev', '.')] if 'close' in ctx.extra(): ui.write('cannot verify closed branch') return 0 convert_revision = ctx.extra().get('convert_revision') if convert_revision is None or not convert_revision.startswith('svn:'): raise error.Abort('revision %s not from SVN' % ctx) if args: url = repo.ui.expandpath(args[0]) else: url = repo.ui.expandpath('default') svn = svnrepo.svnremoterepo(ui, url).svn meta = repo.svnmeta(svn.uuid, svn.subdir) srev, branch, branchpath = meta.get_source_rev(ctx=ctx) branchpath = branchpath[len(svn.subdir.lstrip('/')):] branchurl = ('%s/%s' % (url, branchpath)).strip('/') ui.write('verifying %s against %s@%i\n' % (ctx, branchurl, srev)) def diff_file(path, svndata): fctx = ctx[path] if ui.verbose and not fctx.isbinary(): svndesc = '%s/%s/%s@%d' % (svn.svn_url, branchpath, path, srev) hgdesc = '%s@%s' % (path, ctx) for c in difflib.unified_diff(svndata.splitlines(True), fctx.data().splitlines(True), svndesc, hgdesc): ui.note(c) if opts.get('stupid', ui.configbool('hgsubversion', 'stupid')): svnfiles = set() result = 0 hgfiles = set(ctx) - util.ignoredfiles def verifydata(svndata): svnworker = svnrepo.svnremoterepo(ui, url).svn i = 0 res = True for fn, type in svndata: i += 1 if type != 'f': continue fp = fn if branchpath: fp = branchpath + '/' + fn data, mode = svnworker.get_file(posixpath.normpath(fp), srev) try: fctx = ctx[fn] except error.LookupError: yield i, "%s\0%r" % (fn, res) continue if not fctx.data() == data: ui.write('difference in: %s\n' % fn) diff_file(fn, data) res = False if not fctx.flags() == mode: ui.write('wrong flags for: %s\n' % fn) res = False yield i, "%s\0%r" % (fn, res) if url.startswith('file://'): perarg = 0.00001 else: perarg = 0.000001 svndata = svn.list_files(branchpath, srev) w = worker.worker(repo.ui, perarg, verifydata, (), tuple(svndata)) i = 0 for _, t in w: compathacks.progress(ui, 'verify', i, total=len(hgfiles)) i += 1 fn, ok = t.split('\0', 2) if not bool(ok): result = 1 svnfiles.add(fn) if hgfiles != svnfiles: unexpected = hgfiles - svnfiles for f in sorted(unexpected): ui.write('unexpected file: %s\n' % f) missing = svnfiles - hgfiles for f in sorted(missing): ui.write('missing file: %s\n' % f) result = 1 compathacks.progress(ui, 'verify', None, total=len(hgfiles)) else: class VerifyEditor(svnwrap.Editor): """editor that verifies a repository against the given context.""" def __init__(self, ui, ctx): self.ui = ui self.ctx = ctx self.unexpected = set(ctx) - util.ignoredfiles self.missing = set() self.failed = False self.total = len(self.unexpected) self.seen = 0 def open_root(self, base_revnum, pool=None): pass def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, pool=None): self.file = None self.props = None def open_directory(self, path, parent_baton, base_revision, pool=None): self.file = None self.props = None def add_file(self, path, parent_baton=None, copyfrom_path=None, copyfrom_revision=None, file_pool=None): if path in self.unexpected: self.unexpected.remove(path) self.file = path self.props = {} else: self.total += 1 self.missing.add(path) self.failed = True self.file = None self.props = None self.seen += 1 compathacks.progress(self.ui, 'verify', self.seen, total=self.total) def open_file(self, path, base_revnum): raise NotImplementedError() def apply_textdelta(self, file_baton, base_checksum, pool=None): stream = svnwrap.SimpleStringIO(closing=False) handler = svnwrap.apply_txdelta('', stream) if not callable(handler): raise error.Abort('Error in Subversion bindings: ' 'cannot call handler!') def txdelt_window(window): handler(window) # window being None means we're done if window: return fctx = self.ctx[self.file] hgdata = fctx.data() svndata = stream.getvalue() if 'svn:executable' in self.props: if fctx.flags() != 'x': self.ui.write('wrong flags for: %s\n' % self.file) self.failed = True elif 'svn:special' in self.props: hgdata = 'link ' + hgdata if fctx.flags() != 'l': self.ui.write('wrong flags for: %s\n' % self.file) self.failed = True elif fctx.flags(): self.ui.write('wrong flags for: %s\n' % self.file) self.failed = True if hgdata != svndata: self.ui.write('difference in: %s\n' % self.file) diff_file(self.file, svndata) self.failed = True if self.file is not None: return txdelt_window def change_dir_prop(self, dir_baton, name, value, pool=None): pass def change_file_prop(self, file_baton, name, value, pool=None): if self.props is not None: self.props[name] = value def close_file(self, file_baton, checksum, pool=None): pass def close_directory(self, dir_baton, pool=None): pass def delete_entry(self, path, revnum, pool=None): raise NotImplementedError() def check(self): compathacks.progress(self.ui, 'verify', None, total=self.total) for f in self.unexpected: self.ui.write('unexpected file: %s\n' % f) self.failed = True for f in self.missing: self.ui.write('missing file: %s\n' % f) self.failed = True return not self.failed v = VerifyEditor(ui, ctx) svnrepo.svnremoterepo(ui, branchurl).svn.get_revision(srev, v) if v.check(): result = 0 else: result = 1 return result
last_rev = -1 if not partial and os.path.exists(meta.tagfile): os.unlink(meta.tagfile) skipped = set() closed = set() numrevs = len(repo) - startrev # ctx.children() visits all revisions in the repository after ctx. Calling # it would make us use O(revisions^2) time, so we perform an extra traversal # of the repository instead. During this traversal, we find all converted # changesets that close a branch, and store their first parent for ctx in util.get_contexts(repo, startrev): compathacks.progress(ui, 'prepare', ctx.rev() - startrev, total=numrevs) convinfo = util.getsvnrev(ctx, None) if not convinfo: continue svnrevnum = int(convinfo.rsplit('@', 1)[1]) youngest = max(youngest, svnrevnum) if ctx.extra().get('close', None) is None: continue droprev = lambda x: x.rsplit('@', 1)[0] parentctx = ctx.parents()[0] parentinfo = util.getsvnrev(parentctx, '@')