예제 #1
0
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]
예제 #2
0
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]
예제 #3
0
 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
예제 #4
0
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')
예제 #5
0
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
예제 #6
0
    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))
예제 #7
0
 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
예제 #8
0
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)
예제 #9
0
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')
예제 #10
0
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]
예제 #11
0
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)')
        })
예제 #12
0
 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)
예제 #13
0
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
예제 #14
0
    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)