def repository(_ui=None, path='', create=False, bundle=None): '''Returns a subclassed Mercurial repository to which new THG-specific methods have been added. The repository object is obtained using mercurial.hg.repository()''' if bundle: if _ui is None: _ui = uimod.ui() repo = bundlerepo.bundlerepository(_ui, path, bundle) repo.__class__ = _extendrepo(repo) repo._pyqtobj = ThgRepoWrapper(repo) return repo if create or path not in _repocache: if _ui is None: _ui = uimod.ui() try: repo = hg.repository(_ui, path, create) repo.__class__ = _extendrepo(repo) repo._pyqtobj = ThgRepoWrapper(repo) _repocache[path] = repo return repo except EnvironmentError: raise error.RepoError('Cannot open repository at %s' % path) if not os.path.exists(os.path.join(path, '.hg/')): del _repocache[path] # this error must be in local encoding raise error.RepoError('%s is not a valid repository' % path) return _repocache[path]
def repository(_ui=None, path='', bundle=None): '''Returns a subclassed Mercurial repository to which new THG-specific methods have been added. The repository object is obtained using mercurial.hg.repository()''' if bundle: if _ui is None: _ui = uimod.ui() repo = bundlerepo.bundlerepository(_ui, path, bundle) repo.__class__ = _extendrepo(repo) agent = RepoAgent(repo) return agent.rawRepo() if path not in _repocache: if _ui is None: _ui = uimod.ui() try: repo = hg.repository(_ui, path) # get unfiltered repo in version safe manner repo = getattr(repo, 'unfiltered', lambda: repo)() repo.__class__ = _extendrepo(repo) agent = RepoAgent(repo) _repocache[path] = agent.rawRepo() return agent.rawRepo() except EnvironmentError: raise error.RepoError('Cannot open repository at %s' % path) if not os.path.exists(os.path.join(path, '.hg/')): del _repocache[path] # this error must be in local encoding raise error.RepoError('%s is not a valid repository' % path) return _repocache[path]
def __init__(self, ui, path, rev=None): converter_source.__init__(self, ui, path, rev) self.ignoreerrors = ui.configbool('convert', 'hg.ignoreerrors', False) self.ignored = set() self.saverev = ui.configbool('convert', 'hg.saverev', False) try: self.repo = hg.repository(self.ui, path) # try to provoke an exception if this isn't really a hg # repo, but some other bogus compatible-looking url if not self.repo.local(): raise error.RepoError() except error.RepoError: ui.traceback() raise NoRepo("%s is not a local Mercurial repo" % path) self.lastrev = None self.lastctx = None self._changescache = None self.convertfp = None # Restrict converted revisions to startrev descendants startnode = ui.config('convert', 'hg.startrev') if startnode is not None: try: startnode = self.repo.lookup(startnode) except error.RepoError: raise util.Abort( _('%s is not a valid start revision') % startnode) startrev = self.repo.changelog.rev(startnode) children = {startnode: 1} for rev in self.repo.changelog.descendants(startrev): children[self.repo.changelog.node(rev)] = 1 self.keep = children.__contains__ else: self.keep = util.always
def genignore(ui, repo, force=False, **opts): """generate .hgignore from svn:ignore properties. """ if repo is None: raise error.RepoError("There is no Mercurial repository" " here (.hg not found)") ignpath = repo.wjoin('.hgignore') if not force and os.path.exists(ignpath): raise hgutil.Abort('not overwriting existing .hgignore, try --force?') svn = svnrepo.svnremoterepo(repo.ui).svn meta = repo.svnmeta() hashes = meta.revmap.hashes() parent = util.parentrev(ui, repo, meta, hashes) r, br = hashes[parent.node()] branchpath = meta.layoutobj.remotename(br) if branchpath: branchpath += '/' ignorelines = ['.hgignore', 'syntax:glob'] dirs = [''] + [d[0] for d in svn.list_files(branchpath, r) if d[1] == 'd'] for dir in dirs: path = '%s%s' % (branchpath, dir) props = svn.list_props(path, r) if 'svn:ignore' not in props: continue lines = props['svn:ignore'].strip().split('\n') ignorelines += [dir and (dir + '/' + prop) or prop for prop in lines if prop.strip()] repo.wopener('.hgignore', 'w').write('\n'.join(ignorelines) + '\n')
def liveversion(): 'Attempt to read the version from the live repository' utilpath = os.path.dirname(os.path.realpath(__file__)) thgpath = os.path.dirname(os.path.dirname(utilpath)) if not os.path.isdir(os.path.join(thgpath, '.hg')): raise error.RepoError(_('repository %s not found') % thgpath) u = ui.ui() # prevent loading additional extensions for k, _v in u.configitems('extensions'): u.setconfig('extensions', k, '!') repo = hg.repository(u, path=thgpath) u.pushbuffer() commands.identify(u, repo, id=True, tags=True, rev='.') l = u.popbuffer().split() while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags l.pop() if len(l) > 1: # tag found version = l[-1] if l[0].endswith('+'): # propagate the dirty status to the tag version += '+' elif len(l) == 1: # no tag found u.pushbuffer() commands.parents(u, repo, template='{latesttag}+{latesttagdistance}-') version = u.popbuffer().rpartition(':')[2] + l[0] return repo[None].branch(), version
def get(self, files): '''Get the specified big files from the store and write to local files under repo.root. files is a list of (filename, hash) tuples. Return (success, missing), lists of files successfuly downloaded and those not found in the store. success is a list of (filename, hash) tuples; missing is a list of filenames that we could not get. (The detailed error message will already have been presented to the user, so missing is just supplied as a summary.)''' success = [] missing = [] ui = self.ui at = 0 for filename, hash in files: ui.progress(_('Getting kbfiles'), at, unit='kbfile', total=len(files)) at += 1 ui.note(_('getting %s\n') % filename) outfilename = self.repo.wjoin(filename) destdir = os.path.dirname(outfilename) util.makedirs(destdir) if not os.path.isdir(destdir): self.abort( error.RepoError( _('cannot create dest directory %s') % destdir)) # No need to pass mode='wb' to fdopen(), since mkstemp() already # opened the file in binary mode. (tmpfd, tmpfilename) = tempfile.mkstemp(dir=destdir, prefix=os.path.basename(filename)) tmpfile = os.fdopen(tmpfd, 'w') try: bhash = self._getfile(tmpfile, filename, hash) except StoreError, err: ui.warn(err.longmessage()) os.remove(tmpfilename) missing.append(filename) continue hhash = binascii.hexlify(bhash) if hhash != hash: ui.warn( _('%s: data corruption (expected %s, got %s)\n') % (filename, hash, hhash)) os.remove(tmpfilename) missing.append(filename) else: if os.path.exists(outfilename): # for windows os.remove(outfilename) os.rename(tmpfilename, outfilename) bfutil.copy_to_cache(self.repo, self.repo['.'].node(), filename, True) success.append((filename, hhash))
def make_handler(): if webdir_conf: hgwebobj = hgwebdir(webdir_conf, ui) elif repo is not None: hgwebobj = hgweb(hg.repository(repo.ui, repo.root)) else: raise error.RepoError(_("There is no Mercurial repository" " here (.hg not found)")) return hgwebobj
def runcommand(ui, args): cmd, func, args, options, cmdoptions, alias = _parse(ui, args) cmdoptions['alias'] = alias ui.setconfig("ui", "verbose", str(bool(options["verbose"]))) i18n.setlanguage(ui.config('tortoisehg', 'ui.language')) if options['help']: return help_(ui, cmd) if options['newworkbench']: cmdoptions['newworkbench'] = True path = options['repository'] if path: if path.startswith('bundle:'): s = path[7:].split('+', 1) if len(s) == 1: path, bundle = os.getcwd(), s[0] else: path, bundle = s cmdoptions['bundle'] = os.path.abspath(bundle) path = ui.expandpath(path) if not os.path.exists(path) or not os.path.isdir(path + '/.hg'): print 'abort: %s is not a repository' % path return 1 os.chdir(path) if options['fork']: cmdoptions['fork'] = True if options['nofork'] or options['profile']: cmdoptions['nofork'] = True path = paths.find_root(os.getcwd()) if path: cmdoptions['repository'] = path try: lui = ui.copy() lui.readconfig(os.path.join(path, ".hg", "hgrc")) except IOError: pass else: lui = ui hglib.wrapextensionsloader() # enable blacklist of extensions extensions.loadall(lui) args += get_files_from_listfile() if options['quiet']: ui.quiet = True if cmd not in nonrepo_commands.split() and not path: raise error.RepoError( _("There is no Mercurial repository here" " (.hg not found)")) cmdoptions['mainapp'] = True d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) return _runcommand(lui, options, cmd, d)
def _buildmeta(ui, repo, args, partial=False, skipuuid=False): if repo is None: raise error.RepoError("There is no Mercurial repository" " here (.hg not found)") dest = None validateuuid = False if len(args) == 1: dest = args[0] validateuuid = True elif len(args) > 1: raise error.Abort('rebuildmeta takes 1 or no arguments') url = repo.ui.expandpath(dest or repo.ui.config('paths', 'default-push') or repo.ui.config('paths', 'default') or '') meta = svnmeta.SVNMeta(repo, skiperrorcheck=True) svn = None if meta.subdir is None: svn = svnrepo.svnremoterepo(ui, url).svn meta.subdir = svn.subdir youngest = 0 startrev = 0 branchinfo = {} if not partial: hgutil.unlinkpath(meta.revmap_file, ignoremissing=True) revmap = meta.revmap if partial: try: # we can't use meta.lastpulled here because we are bootstraping the # lastpulled and want to keep the cached value on disk during a # partial rebuild foundpartialinfo = False youngestpath = os.path.join(meta.metapath, 'lastpulled') if os.path.exists(youngestpath): youngest = util.load(youngestpath) lasthash = revmap.lasthash if len(revmap) > 0 and lasthash: startrev = repo[lasthash].rev() + 1 branchinfo = util.load(meta.branch_info_file) foundpartialinfo = True if not foundpartialinfo: ui.status('missing some metadata -- doing a full rebuild\n') partial = False except IOError, err: if err.errno != errno.ENOENT: raise ui.status('missing some metadata -- doing a full rebuild\n') except AttributeError: ui.status('no metadata available -- doing a full rebuild\n')
def repository(_ui=None, path=''): '''Returns a subclassed Mercurial repository to which new THG-specific methods have been added. The repository object is obtained using mercurial.hg.repository()''' if path not in _repocache: if _ui is None: _ui = hglib.loadui() try: repo = hg.repository(_ui, path) repo = repo.unfiltered() repo.__class__ = _extendrepo(repo) repo = repo.filtered('visible') agent = RepoAgent(repo) _repocache[path] = agent.rawRepo() return agent.rawRepo() except EnvironmentError: raise error.RepoError('Cannot open repository at %s' % path) if not os.path.exists(os.path.join(path, '.hg/')): del _repocache[path] # this error must be in local encoding raise error.RepoError('%s is not a valid repository' % path) return _repocache[path]
def info(ui, repo, **opts): """show Subversion details similar to `svn info' """ if repo is None: raise error.RepoError("There is no Mercurial repository" " here (.hg not found)") meta = repo.svnmeta() hashes = meta.revmap.hashes() if opts.get('rev'): parent = repo[opts['rev']] else: parent = util.parentrev(ui, repo, meta, hashes) pn = parent.node() if pn not in hashes: ui.status('Not a child of an svn revision.\n') return 0 r, br = hashes[pn] subdir = util.getsvnrev(parent)[40:].split('@')[0] remoterepo = svnrepo.svnremoterepo(repo.ui) url = meta.layoutobj.remotepath(br, remoterepo.svnurl) author = meta.authors.reverselookup(parent.user()) # cleverly figure out repo root w/o actually contacting the server reporoot = url[:len(url) - len(subdir)] ui.write( '''URL: %(url)s Repository Root: %(reporoot)s Repository UUID: %(uuid)s Revision: %(revision)s Node Kind: directory Last Changed Author: %(author)s Last Changed Rev: %(revision)s Last Changed Date: %(date)s\n''' % { 'reporoot': reporoot, 'uuid': meta.uuid, 'url': url, 'author': author, 'revision': r, # TODO I'd like to format this to the user's local TZ if possible 'date': compathacks.datestr(parent.date(), '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') })
def __init__(self, *args, **kwargs): if self.address_family is None: raise error.RepoError(_('IPv6 is not available on this system')) super(IPv6HTTPServer, self).__init__(*args, **kwargs)
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
def __init__(self, baseui, path, create=False, intents=None): # type: (uimod.ui, str, bool, Any) -> None self.requirements = set() self.filtername = None self._phasedefaults = [] self._bookmarks = {} self.obsstore = False self._revbranchcache = None # generic mapping between names and nodes self.names = gitnamespaces() # wvfs: rooted at the repository root, used to access the working copy self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True) # vfs: rooted at .hg, used to access repo files outside of .hg/store self.vfs = None # svfs: usually rooted at .hg/store, used to access repository history # If this is a shared repository, this vfs may point to another # repository's .hg/store directory. self.svfs = None self.root = self.wvfs.base self.path = self.wvfs.join(".git") self.origroot = path # This is only used by context.workingctx.match in order to # detect files in subrepos. self.auditor = pathutil.pathauditor(self.root, callback=self._checknested) # This is only used by context.basectx.match in order to detect # files in subrepos. self.nofsauditor = pathutil.pathauditor(self.root, callback=self._checknested, realfs=False, cached=True) self.baseui = baseui self.ui = baseui.copy() self.ui.copy = baseui.copy # prevent copying repo configuration self.vfs = vfsmod.vfs(self.path, cacheaudited=True) if (self.ui.configbool('devel', 'all-warnings') or self.ui.configbool('devel', 'check-locks')): self.vfs.audit = self._getvfsward(self.vfs.audit) try: self.ui.readconfig(self.vfs.join("hgrc"), self.root) # self._loadextensions() except IOError: pass color.setup(self.ui) if not self.vfs.isdir(): if create: pygit2.init_repository(self.path, False) else: raise error.RepoError(_("repository %s not found") % path) elif create: raise error.RepoError(_("repository %s already exists") % path) self._repo = pygit2.Repository(self.path) # FIXME: move to propertycache self.dirstate = gitdirstate(self, self.ui, self.root)