def openstore(repo=None, remote=None, put=False, ui=None):
    if ui is None:
        ui = repo.ui

    if not remote:
        lfpullsource = getattr(repo, 'lfpullsource', None)
        if lfpullsource:
            path = ui.expandpath(lfpullsource)
        elif put:
            path = ui.expandpath('default-push', 'default')
        else:
            path = ui.expandpath('default')

        # ui.expandpath() leaves 'default-push' and 'default' alone if
        # they cannot be expanded: fallback to the empty string,
        # meaning the current directory.
        if repo is None:
            path = ui.expandpath('default')
            path, _branches = hg.parseurl(path)
            remote = hg.peer(repo or ui, {}, path)
        elif path == 'default-push' or path == 'default':
            path = ''
            remote = repo
        else:
            path, _branches = hg.parseurl(path)
            remote = hg.peer(repo or ui, {}, path)

    # The path could be a scheme so use Mercurial's normal functionality
    # to resolve the scheme to a repository and use its path
    path = util.safehasattr(remote, 'url') and remote.url() or remote.path

    match = _scheme_re.match(path)
    if not match:  # regular filesystem path
        scheme = 'file'
    else:
        scheme = match.group(1)

    try:
        storeproviders = _storeprovider[scheme]
    except KeyError:
        raise error.Abort(_('unsupported URL scheme %r') % scheme)

    for classobj in storeproviders:
        try:
            return classobj(ui, repo, remote)
        except lfutil.storeprotonotcapable:
            pass

    raise error.Abort(
        _('%s does not appear to be a largefile store') %
        util.hidepassword(path))
Example #2
0
def goutgoing(ui, repo, dest=None, **opts):
    """show the outgoing changesets alongside an ASCII revision graph

    Print the outgoing changesets alongside a revision graph drawn with
    ASCII characters.

    Nodes printed as an @ character are parents of the working
    directory.
    """

    check_unsupported_flags(opts)
    dest, revs, checkout = hg.parseurl(
        ui.expandpath(dest or 'default-push', dest or 'default'),
        opts.get('rev'))
    if revs:
        revs = [repo.lookup(rev) for rev in revs]
    other = hg.repository(cmdutil.remoteui(ui, opts), dest)
    ui.status(_('comparing with %s\n') % url.hidepassword(dest))
    o = repo.findoutgoing(other, force=opts.get('force'))
    if not o:
        ui.status(_("no changes found\n"))
        return

    o = repo.changelog.nodesbetween(o, revs)[0]
    revdag = graphrevs(repo, o, opts)
    fmtdag = asciiformat(ui, repo, revdag, opts)
    ascii(ui, asciiedges(fmtdag))
Example #3
0
def goutgoing(ui, repo, dest=None, **opts):
    """show the outgoing changesets alongside an ASCII revision graph

    Print the outgoing changesets alongside a revision graph drawn with
    ASCII characters.

    Nodes printed as an @ character are parents of the working
    directory.
    """

    check_unsupported_flags(opts)
    dest = ui.expandpath(dest or 'default-push', dest or 'default')
    dest, branches = hg.parseurl(dest, opts.get('branch'))
    revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
    other = hg.repository(cmdutil.remoteui(ui, opts), dest)
    if revs:
        revs = [repo.lookup(rev) for rev in revs]
    ui.status(_('comparing with %s\n') % url.hidepassword(dest))
    o = repo.findoutgoing(other, force=opts.get('force'))
    if not o:
        ui.status(_("no changes found\n"))
        return

    o = repo.changelog.nodesbetween(o, revs)[0]
    revdag = graphrevs(repo, o, opts)
    displayer = show_changeset(ui, repo, opts, buffered=True)
    showparents = [ctx.node() for ctx in repo[None].parents()]
    generate(ui, revdag, displayer, showparents, asciiedges)
Example #4
0
def findoutgoing(ui, repo, remote=None, force=False, opts=None):
    """utility function to find the first outgoing changeset

    Used by initialization code"""
    if opts is None:
        opts = {}
    dest = ui.expandpath(remote or 'default-push', remote or 'default')
    dest, revs = hg.parseurl(dest, None)[:2]
    ui.status(_('comparing with %s\n') % util.hidepassword(dest))

    revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
    other = hg.peer(repo, opts, dest)

    if revs:
        revs = [repo.lookup(rev) for rev in revs]

    outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
    if not outgoing.missing:
        raise error.Abort(_('no outgoing ancestors'))
    roots = list(repo.revs("roots(%ln)", outgoing.missing))
    if 1 < len(roots):
        msg = _('there are ambiguous outgoing revisions')
        hint = _('see "hg help histedit" for more detail')
        raise error.Abort(msg, hint=hint)
    return repo.lookup(roots[0])
Example #5
0
def get_repo(alias, url):
    """Returns a hg.repository object initialized for usage.
    """

    try:
        from mercurial import hg, ui
    except ImportError:
        die("Mercurial python libraries not installed")

    ui = ui.ui()
    source, revs = hg.parseurl(ui.expandpath(url), ['tip'])
    repo = hg.repository(ui, source)

    prefix = 'refs/hg/%s/' % alias
    debug("prefix: '%s'", prefix)

    repo.hg = hg
    repo.gitdir = ""
    repo.alias = alias
    repo.prefix = prefix
    repo.revs = revs

    repo.git_hg = GitHg(warn)
    exporter = GitExporter(repo.git_hg, repo, 'hg.marks', 'git.marks', prefix)
    non_local = NonLocalHg(repo, alias)

    repo.exporter = exporter
    repo.non_local = non_local

    return repo
Example #6
0
 def validate_hg_url(self, url):
     error = _("Invalid Hg URL: '%s'") % url
     source, branches = hg.parseurl(url)
     try:
         hg.repository(ui.ui(), source)
     except RepoError:
         raise forms.ValidationError(error)
Example #7
0
def diff(orig, ui, repo, *pats, **opts):
    """
    [rdiff]
    If the first argument to the diff command is a remote repository URL,
    the diff will be performed against that URL. If revision arguments are
    given, the first revision is the revision in the source repository,
    and the second revision is looked up in the destination.
    
    The --reverse flag cause the direction of the diff to be reversed.
    """
    url = None
    rrev = None
    if pats:
        path = ui.expandpath(pats[0])
        if hasattr(hg, "parseurl"):
            # parseurl changed from returning two args to three
            args = hg.parseurl(ui.expandpath(pats[0]), [])
            path, rrev = args[0], args[-1]
        if "://" in path or os.path.isdir(os.path.join(path, ".hg")):
            url = path
            pats = pats[1:]

    if url:
        lrev = None
        if len(opts["rev"]) > 2 or rrev and len(opts["rev"]) > 1:
            raise util.Abort(_("too many revisions"))
        if opts["rev"]:
            lrev = opts["rev"][0]
        if len(opts["rev"]) > 1:
            rrev = opts["rev"][1]
        return rdiff(ui, repo, url, lrev, rrev, *pats, **opts)
    else:
        return orig(ui, repo, *pats, **opts)
Example #8
0
def nclone(ui, source, dest=None, **opts):
    '''make a copy of an existing repository and all nested repositories

    Create a copy of an existing repository in a new directory.

    Look at the help of clone command for more informations.'''
    origsource = ui.expandpath(source)
    remotesource, remotebranch = hg.parseurl(origsource, opts.get('branch'))
    if hasattr(hg, 'peer'):
        remoterepo = hg.peer(ui, opts, remotesource)
        localrepo = remoterepo.local()
        if localrepo:
            remoterepo = localrepo
    else:
        remoterepo = hg.repository(hg.remoteui(ui, opts), remotesource)
    if dest is None:
        dest = hg.defaultdest(source)
        ui.status(_("destination directory: %s\n") % dest)
    for npath in remoterepo.nested:
        if npath == '.':
            npath = ''
        u = util.url(source)
        if u.scheme:
            nsource = '%s/%s' % (source, npath)
        else:
            nsource = os.path.join(source, npath)
        ndest = os.path.join(dest, npath)
        ui.status('[%s]\n' % os.path.normpath(
            os.path.join(os.path.basename(dest),
                ndest[len(dest) + 1:])))
        commands.clone(ui, nsource, dest=ndest, **opts)
        ui.status('\n')
Example #9
0
def _findbundle(repo, rev):
    """Returns the backup bundle that contains the given rev. If found, it
    returns the bundle peer and the full rev hash. If not found, it return None
    and the given rev value.
    """
    ui = repo.ui
    backuppath = repo.vfs.join("strip-backup")
    backups = filter(os.path.isfile, glob.glob(backuppath + "/*.hg"))
    backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
    for backup in backups:
        # Much of this is copied from the hg incoming logic
        source = os.path.relpath(backup, pycompat.getcwd())
        source = ui.expandpath(source)
        source, branches = hg.parseurl(source)
        other = hg.peer(repo, {}, source)

        quiet = ui.quiet
        try:
            ui.quiet = True
            ret = bundlerepo.getremotechanges(ui, repo, other, None, None, None)
            localother, chlist, cleanupfn = ret
            for node in chlist:
                if hex(node).startswith(rev):
                    return other, node
        except error.LookupError:
            continue
        finally:
            ui.quiet = quiet

    return None, rev
Example #10
0
def pull(oldpull, ui, repo, source="default", **opts):
    # translate bookmark args to rev args for actual pull
    if opts.get('bookmark'):
        # this is an unpleasant hack as pull will do this internally
        source, branches = hg.parseurl(ui.expandpath(source),
                                       opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), source)
        rb = other.listkeys('bookmarks')

        for b in opts['bookmark']:
            if b not in rb:
                raise util.Abort(_('remote bookmark %s not found!') % b)
            opts.setdefault('rev', []).append(b)

    result = oldpull(ui, repo, source, **opts)

    # update specified bookmarks
    if opts.get('bookmark'):
        for b in opts['bookmark']:
            # explicit pull overrides local bookmark if any
            ui.status(_("importing bookmark %s\n") % b)
            repo._bookmarks[b] = repo[rb[b]].node()
        write(repo)

    return result
Example #11
0
def goutgoing(ui, repo, dest=None, **opts):
    """show the outgoing changesets alongside an ASCII revision graph

    Print the outgoing changesets alongside a revision graph drawn with
    ASCII characters.

    Nodes printed as an @ character are parents of the working
    directory.
    """

    check_unsupported_flags(opts)
    dest, revs, checkout = hg.parseurl(
        ui.expandpath(dest or 'default-push', dest or 'default'),
        opts.get('rev'))
    if revs:
        revs = [repo.lookup(rev) for rev in revs]
    other = hg.repository(cmdutil.remoteui(ui, opts), dest)
    ui.status(_('comparing with %s\n') % url.hidepassword(dest))
    o = repo.findoutgoing(other, force=opts.get('force'))
    if not o:
        ui.status(_("no changes found\n"))
        return

    o = repo.changelog.nodesbetween(o, revs)[0]
    revdag = graphrevs(repo, o, opts)
    fmtdag = asciiformat(ui, repo, revdag, opts)
    ascii(ui, asciiedges(fmtdag))
	def outgoing(self):
		limit = cmdutil.loglimit(opts)
		dest, revs, checkout = hg.parseurl(
			ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
		if revs:
			revs = [repo.lookup(rev) for rev in revs]

		other = hg.repository(cmdutil.remoteui(repo, opts), dest)
		ui.status(_('comparing with %s\n') % url.hidepassword(dest))
		o = repo.findoutgoing(other, force=opts.get('force'))
		if not o:
			ui.status(_("no changes found\n"))
			return 1
		o = repo.changelog.nodesbetween(o, revs)[0]
		if opts.get('newest_first'):
			o.reverse()
		displayer = cmdutil.show_changeset(ui, repo, opts)
		count = 0
		for n in o:
			if count >= limit:
				break
			parents = [p for p in repo.changelog.parents(n) if p != nullid]
			if opts.get('no_merges') and len(parents) == 2:
				continue
			count += 1
			displayer.show(repo[n])
Example #13
0
def incoming(oldincoming, ui, repo, source="default", **opts):
    if opts.get('bookmarks'):
        source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), source)
        ui.status(_('comparing with %s\n') % url.hidepassword(source))
        return diffbookmarks(ui, repo, other)
    else:
        return oldincoming(ui, repo, source, **opts)
Example #14
0
def find_pull_peer(repo, opts, source):
    source, branches = hg.parseurl(repo.ui.expandpath(source), opts.get('branch'))
    try:
        return hg.peer(repo, opts, source)
    except error.RepoError:
        if source == "default":
            return
        else:
            raise
Example #15
0
def outgoing(oldoutgoing, ui, repo, dest=None, **opts):
    if opts.get('bookmarks'):
        dest = ui.expandpath(dest or 'default-push', dest or 'default')
        dest, branches = hg.parseurl(dest, opts.get('branch'))
        other = hg.repository(hg.remoteui(repo, opts), dest)
        ui.status(_('comparing with %s\n') % url.hidepassword(dest))
        return diffbookmarks(ui, other, repo)
    else:
        return oldoutgoing(ui, repo, dest, **opts)
	def incoming(self):
		limit = cmdutil.loglimit(opts)
		source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
		other = hg.repository(cmdutil.remoteui(repo, opts), source)
		ui.status(_('comparing with %s\n') % url.hidepassword(source))
		if revs:
			revs = [other.lookup(rev) for rev in revs]
		common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
                                                       force=opts["force"])
		if not incoming:
			try:
				os.unlink(opts["bundle"])
			except:
				pass
			ui.status(_("no changes found\n"))
			return 1

		cleanup = None
		try:
			fname = opts["bundle"]
			if fname or not other.local():
				# create a bundle (uncompressed if other repo is not local)

				if revs is None and other.capable('changegroupsubset'):
					revs = rheads

				if revs is None:
					cg = other.changegroup(incoming, "incoming")
				else:
					cg = other.changegroupsubset(incoming, revs, 'incoming')
				bundletype = other.local() and "HG10BZ" or "HG10UN"
				fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
				# keep written bundle?
				if opts["bundle"]:
					cleanup = None
				if not other.local():
					# use the created uncompressed bundlerepo
					other = bundlerepo.bundlerepository(ui, repo.root, fname)

			o = other.changelog.nodesbetween(incoming, revs)[0]
			if opts.get('newest_first'):
				o.reverse()
			displayer = cmdutil.show_changeset(ui, other, opts)
			count = 0
			for n in o:
				if count >= limit:
					break
				parents = [p for p in other.changelog.parents(n) if p != nullid]
				if opts.get('no_merges') and len(parents) == 2:
					continue
				count += 1
				displayer.show(other[n])
		finally:
			if hasattr(other, 'close'):
				other.close()
			if cleanup:
				os.unlink(cleanup)
Example #17
0
def gincoming(ui, repo, source="default", **opts):
    """show the incoming changesets alongside an ASCII revision graph

    Print the incoming changesets alongside a revision graph drawn with
    ASCII characters.

    Nodes printed as an @ character are parents of the working
    directory.
    """

    check_unsupported_flags(opts)
    source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
    other = hg.repository(cmdutil.remoteui(repo, opts), source)
    revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
    ui.status(_('comparing with %s\n') % url.hidepassword(source))
    if revs:
        revs = [other.lookup(rev) for rev in revs]
    incoming = repo.findincoming(other, heads=revs, force=opts["force"])
    if not incoming:
        try:
            os.unlink(opts["bundle"])
        except:
            pass
        ui.status(_("no changes found\n"))
        return

    cleanup = None
    try:

        fname = opts["bundle"]
        if fname or not other.local():
            # create a bundle (uncompressed if other repo is not local)
            if revs is None:
                cg = other.changegroup(incoming, "incoming")
            else:
                cg = other.changegroupsubset(incoming, revs, 'incoming')
            bundletype = other.local() and "HG10BZ" or "HG10UN"
            fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
            # keep written bundle?
            if opts["bundle"]:
                cleanup = None
            if not other.local():
                # use the created uncompressed bundlerepo
                other = bundlerepo.bundlerepository(ui, repo.root, fname)

        chlist = other.changelog.nodesbetween(incoming, revs)[0]
        revdag = graphrevs(other, chlist, opts)
        displayer = show_changeset(ui, other, opts, buffered=True)
        showparents = [ctx.node() for ctx in repo[None].parents()]
        generate(ui, revdag, displayer, showparents, asciiedges)

    finally:
        if hasattr(other, 'close'):
            other.close()
        if cleanup:
            os.unlink(cleanup)
Example #18
0
def _pull(orig, ui, repo, source="default", **opts):
    opts = pycompat.byteskwargs(opts)
    # Copy paste from `pull` command
    source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))

    scratchbookmarks = {}
    unfi = repo.unfiltered()
    unknownnodes = []
    for rev in opts.get('rev', []):
        if rev not in unfi:
            unknownnodes.append(rev)
    if opts.get('bookmark'):
        bookmarks = []
        revs = opts.get('rev') or []
        for bookmark in opts.get('bookmark'):
            if _scratchbranchmatcher(bookmark):
                # rev is not known yet
                # it will be fetched with listkeyspatterns next
                scratchbookmarks[bookmark] = 'REVTOFETCH'
            else:
                bookmarks.append(bookmark)

        if scratchbookmarks:
            other = hg.peer(repo, opts, source)
            fetchedbookmarks = other.listkeyspatterns(
                'bookmarks', patterns=scratchbookmarks)
            for bookmark in scratchbookmarks:
                if bookmark not in fetchedbookmarks:
                    raise error.Abort('remote bookmark %s not found!' %
                                      bookmark)
                scratchbookmarks[bookmark] = fetchedbookmarks[bookmark]
                revs.append(fetchedbookmarks[bookmark])
        opts['bookmark'] = bookmarks
        opts['rev'] = revs

    if scratchbookmarks or unknownnodes:
        # Set anyincoming to True
        extensions.wrapfunction(discovery, 'findcommonincoming',
                                _findcommonincoming)
    try:
        # Remote scratch bookmarks will be deleted because remotenames doesn't
        # know about them. Let's save it before pull and restore after
        remotescratchbookmarks = _readscratchremotebookmarks(ui, repo, source)
        result = orig(ui, repo, source, **pycompat.strkwargs(opts))
        # TODO(stash): race condition is possible
        # if scratch bookmarks was updated right after orig.
        # But that's unlikely and shouldn't be harmful.
        if common.isremotebooksenabled(ui):
            remotescratchbookmarks.update(scratchbookmarks)
            _saveremotebookmarks(repo, remotescratchbookmarks, source)
        else:
            _savelocalbookmarks(repo, scratchbookmarks)
        return result
    finally:
        if scratchbookmarks:
            extensions.unwrapfunction(discovery, 'findcommonincoming')
Example #19
0
File: util.py Project: Grahack/git
def parseurl(url, heads=[]):
    url, heads = hg.parseurl(url, heads)
    if isinstance(heads, tuple) and len(heads) == 2:
        # hg 1.6 or later
        _junk, heads = heads
    if heads:
        checkout = heads[0]
    else:
        checkout = None
    return url, heads, checkout
Example #20
0
def parseurl(url, heads=[]):
    url, heads = hg.parseurl(url, heads)
    if isinstance(heads, tuple) and len(heads) == 2:
        # hg 1.6 or later
        _junk, heads = heads
    if heads:
        checkout = heads[0]
    else:
        checkout = None
    return url, heads, checkout
Example #21
0
def find_push_peer(repo, opts, dest):
    dest = repo.ui.expandpath(dest or 'default-push', dest or 'default')
    dest, branches = hg.parseurl(dest, opts.get('branch'))

    try:
        return hg.peer(repo, opts, dest)
    except error.RepoError:
        if dest == "default-push":
            return
        else:
            raise
Example #22
0
def _getsrcrepo(repo):
    """
    Returns the source repository object for a given shared repository.
    If repo is not a shared repository, return None.
    """
    if repo.sharedpath == repo.path:
        return None

    # the sharedpath always ends in the .hg; we want the path to the repo
    source = repo.vfs.split(repo.sharedpath)[0]
    srcurl, branches = parseurl(source)
    return repository(repo.ui, srcurl)
Example #23
0
def _getsrcrepo(repo):
    """
    Returns the source repository object for a given shared repository.
    If repo is not a shared repository, return None.
    """
    if repo.sharedpath == repo.path:
        return None

    # the sharedpath always ends in the .hg; we want the path to the repo
    source = repo.vfs.split(repo.sharedpath)[0]
    srcurl, branches = parseurl(source)
    return repository(repo.ui, srcurl)
Example #24
0
def parseurl(url, heads=[]):
    parsed = hg.parseurl(url, heads)
    if len(parsed) == 3:
        # old hg, remove when we can be 1.5-only
        svn_url, heads, checkout = parsed
    else:
        svn_url, heads = parsed
        if heads:
            checkout = heads[0]
        else:
            checkout = None
    return svn_url, heads, checkout
Example #25
0
 def test(ui, repo, source, **opts):
     source, branches = hg.parseurl(ui.expandpath(source),
             opts.get('branch'))
     other = hg.repository(hg.remoteui(repo, opts), source)
     revs, checkout = hg.addbranchrevs(repo, other, branches,
             opts.get('rev'))
     if revs:
         try:
             revs = [other.lookup(rev) for rev in revs]
         except CapabilityError:
             err = _("Other repository doesn't support revision lookup, "
                     "so a rev cannot be specified.")
             raise util.Abort(err)
Example #26
0
 def getoutgoing(dest, revs):
     '''Return the revisions present locally but not in dest'''
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
     dest, branches = hg.parseurl(dest)
     revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
     other = hg.peer(repo, opts, dest)
     ui.status(_('comparing with %s\n') % util.hidepassword(dest))
     common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
     nodes = revs and map(repo.lookup, revs) or revs
     o = repo.changelog.findmissing(common, heads=nodes)
     if not o:
         ui.status(_("no changes found\n"))
         return []
     return [str(repo.changelog.rev(r)) for r in o]
	def pull(self):
		source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
		other = hg.repository(cmdutil.remoteui(repo, opts), source)
		ui.status(_('pulling from %s\n') % url.hidepassword(source))
		if revs:
			try:
				revs = [other.lookup(rev) for rev in revs]
			except error.CapabilityError:
				err = _("Other repository doesn't support revision lookup, "
						"so a rev cannot be specified.")
				raise util.Abort(err)

		modheads = repo.pull(other, heads=revs, force=opts.get('force'))
		return postincoming(ui, repo, modheads, opts.get('update'), checkout)
Example #28
0
def _getoutgoing(repo, dest, revs):
    '''Return the revisions present locally but not in dest'''
    ui = repo.ui
    url = ui.expandpath(dest or 'default-push', dest or 'default')
    url = hg.parseurl(url)[0]
    ui.status(_('comparing with %s\n') % util.hidepassword(url))

    revs = [r for r in revs if r >= 0]
    if not revs:
        revs = [len(repo) - 1]
    revs = repo.revs('outgoing(%s) and ::%ld', dest or '', revs)
    if not revs:
        ui.status(_("no changes found\n"))
    return revs
Example #29
0
def _firefoxtreesrepo(repo):
    """Obtain a repo that can open the firefoxtrees file.

    Will return the passed ``repo`` in most cases. But if ``repo``
    is shared, we may return the repo from the share source.
    """
    shared = {s.strip() for s in repo.vfs.tryread('shared').splitlines()}

    if 'firefoxtrees' in shared and repo.sharedpath != repo.path:
        source = repo.vfs.split(repo.sharedpath)[0]
        srcurl, branches = hg.parseurl(source)
        return hg.repository(repo.ui, srcurl)
    else:
        return repo
def _getoutgoing(repo, dest, revs):
    '''Return the revisions present locally but not in dest'''
    ui = repo.ui
    url = ui.expandpath(dest or 'default-push', dest or 'default')
    url = hg.parseurl(url)[0]
    ui.status(_('comparing with %s\n') % util.hidepassword(url))

    revs = [r for r in revs if r >= 0]
    if not revs:
        revs = [len(repo) - 1]
    revs = repo.revs('outgoing(%s) and ::%ld', dest or '', revs)
    if not revs:
        ui.status(_("no changes found\n"))
    return revs
Example #31
0
 def getoutgoing(dest, revs):
     '''Return the revisions present locally but not in dest'''
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
     dest, branches = hg.parseurl(dest)
     revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
     other = hg.peer(repo, opts, dest)
     ui.status(_('comparing with %s\n') % util.hidepassword(dest))
     common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
     nodes = revs and map(repo.lookup, revs) or revs
     o = repo.changelog.findmissing(common, heads=nodes)
     if not o:
         ui.status(_("no changes found\n"))
         return []
     return [str(repo.changelog.rev(r)) for r in o]
Example #32
0
 def test(ui, repo, dest=None, **opts):
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
     dest, branches = hg.parseurl(dest, opts.get('branch'))
     revs, checkout = hg.addbranchrevs(repo, repo, branches,
             opts.get('rev'))
     if hasattr(hg, 'peer'):
         other = hg.peer(ui, opts, dest)
         localother = other.local()
         if localother:
             other = localother
     else:
         other = hg.repository(hg.remoteui(repo, opts), dest)
     if revs:
         revs = [other.lookup(rev) for rev in revs]
Example #33
0
 def outgoing(dest, revs):
     '''Return the revisions present locally but not in dest'''
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
     dest, branches = hg.parseurl(dest)
     revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
     if revs:
         revs = [repo.lookup(rev) for rev in revs]
     other = hg.repository(cmdutil.remoteui(repo, opts), dest)
     ui.status(_('comparing with %s\n') % dest)
     o = repo.findoutgoing(other)
     if not o:
         ui.status(_("no changes found\n"))
         return []
     o = repo.changelog.nodesbetween(o, revs)[0]
     return [str(repo.changelog.rev(r)) for r in o]
Example #34
0
 def getoutgoing(dest, revs):
     '''Return the revisions present locally but not in dest'''
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
     dest, branches = hg.parseurl(dest)
     revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
     if revs:
         revs = [repo.lookup(rev) for rev in revs]
     other = hg.repository(hg.remoteui(repo, opts), dest)
     ui.status(_('comparing with %s\n') % url.hidepassword(dest))
     o = discovery.findoutgoing(repo, other)
     if not o:
         ui.status(_("no changes found\n"))
         return []
     o = repo.changelog.nodesbetween(o, revs)[0]
     return [str(repo.changelog.rev(r)) for r in o]
	def push(self):
		dest, revs, checkout = hg.parseurl(
			ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
		other = hg.repository(cmdutil.remoteui(repo, opts), dest)
		ui.status(_('pushing to %s\n') % url.hidepassword(dest))
		if revs:
			revs = [repo.lookup(rev) for rev in revs]

		# push subrepos depth-first for coherent ordering
		c = repo['']
		subs = c.substate # only repos that are committed
		for s in sorted(subs):
			c.sub(s).push(opts.get('force'))

		r = repo.push(other, opts.get('force'), revs=revs)
Example #36
0
def parseurl(url, heads=[]):
    parsed = hg.parseurl(url, heads)
    if len(parsed) == 3:
        # old hg, remove when we can be 1.5-only
        svn_url, heads, checkout = parsed
    else:
        svn_url, heads = parsed
        if isinstance(heads, tuple) and len(heads) == 2:
            # hg 1.6 or later
            _junk, heads = heads
        if heads:
            checkout = heads[0]
        else:
            checkout = None
    return svn_url, heads, checkout
Example #37
0
def parseurl(url, heads=[]):
    parsed = hg.parseurl(url, heads)
    if len(parsed) == 3:
        # old hg, remove when we can be 1.5-only
        svn_url, heads, checkout = parsed
    else:
        svn_url, heads = parsed
        if isinstance(heads, tuple) and len(heads) == 2:
            # hg 1.6 or later
            _junk, heads = heads
        if heads:
            checkout = heads[0]
        else:
            checkout = None
    return svn_url, heads, checkout
Example #38
0
def parseurl(source):
    '''wrap hg.parseurl to work on 1.5 and 1.6

    1.5 redefined parseurl()'s return values, and 1.6 split up the
    branches parameter into a two-tuple.
    '''
    url, branches = hg.parseurl(source, None)[:2]
    if _HG_VERSION >= (1, 6, 0):
        # branches will be None because we passed None into
        # parseurl(), so we can ignore that safely.
        hashbranch, branches = branches
    else:
        # branches will contain one element or fewer because we passed
        # None into parseurl().
        hashbranch = branches and branches[0] or None
    return url, hashbranch
Example #39
0
def parseurl(source):
    '''wrap hg.parseurl to work on 1.5 and 1.6

    1.5 redefined parseurl()'s return values, and 1.6 split up the
    branches parameter into a two-tuple.
    '''
    url, branches = hg.parseurl(source, None)[:2]
    if _HG_VERSION >= (1, 6, 0):
        # branches will be None because we passed None into
        # parseurl(), so we can ignore that safely.
        hashbranch, branches = branches
    else:
        # branches will contain one element or fewer because we passed
        # None into parseurl().
        hashbranch = branches and branches[0] or None
    return url, hashbranch
Example #40
0
    def push(self, dest=None, rev=None, force=False):
        """\
        Push changes into destination.

        If destination is none, the source of this repo will be used.

        If revision is not specified, the current working dir will be
        pushed.  If this spawns a new head, this operation must be
        forced.

        Forcing will have the side effect of creating a new branch, and
        it may not be desirable.

        By default, no remote branch will be created.
        """

        # find parents
        # if there are two parents, take the first one,
        #   (ui should warn users about uncommitted merge/confirmation)
        # if not force, do it and see if head shows up

        if rev is None:
            rev = [self._repo.lookup('.')]

        dest = self._ui.expandpath(dest or 'default-push', 
                                   dest or 'default')
        repo = self._repo
        dest, branches = hg.parseurl(dest)
        revs, checkout = hg.addbranchrevs(repo, repo, branches, rev)

        if dest in ('default', 'default-push',):
            raise RepoNotFoundError('no suitable target found')
        other = hg.peer(self._repo, {}, dest)
        self._ui.status('pushing to %s\n' % (dest))
        if revs:
            revs = [self._repo.lookup(rev) for rev in revs]
        try:
            r = self._repo.push(other, force, revs=revs)
        except Abort:
            raise ProtocolError()
        # check to see if this revision is present on destination
        # XXX assuming other is localrepo
        try:
            result = other.lookup(revs[0])
        except:
            result = None
        return result is not None
Example #41
0
def _openstore(repo, remote=None, put=False):
    ui = repo.ui

    if not remote:
        lfpullsource = getattr(repo, 'lfpullsource', None)
        if lfpullsource:
            path = ui.expandpath(lfpullsource)
        elif put:
            path = ui.expandpath('default-push', 'default')
        else:
            path = ui.expandpath('default')

        # ui.expandpath() leaves 'default-push' and 'default' alone if
        # they cannot be expanded: fallback to the empty string,
        # meaning the current directory.
        if path == 'default-push' or path == 'default':
            path = ''
            remote = repo
        else:
            path, _branches = hg.parseurl(path)
            remote = hg.peer(repo, {}, path)

    # The path could be a scheme so use Mercurial's normal functionality
    # to resolve the scheme to a repository and use its path
    path = util.safehasattr(remote, 'url') and remote.url() or remote.path

    match = _scheme_re.match(path)
    if not match:  # regular filesystem path
        scheme = 'file'
    else:
        scheme = match.group(1)

    try:
        storeproviders = _storeprovider[scheme]
    except KeyError:
        raise error.Abort(_('unsupported URL scheme %r') % scheme)

    for classobj in storeproviders:
        try:
            return classobj(ui, repo, remote)
        except lfutil.storeprotonotcapable:
            pass

    raise error.Abort(
        _('%s does not appear to be a largefile store') %
        util.hidepassword(path))
Example #42
0
def share(orig, ui, source, *args, **kwargs):
    """Wraps hg.share to mark the firefoxtrees file as shared.

    The .hg/shared file lists things that are shared. We add firefoxtrees
    to it if we are a Firefox repo.
    """
    res = orig(ui, source, *args, **kwargs)

    # TODO Mercurial 3.7 introduces a standalone function that receives the
    # proper arguments so we can avoid this boilerplate.
    if isinstance(source, str):
        origsource = ui.expandpath(source)
        source, branches = hg.parseurl(origsource)
        srcrepo = hg.repository(ui, source)
    else:
        srcrepo = source.local()

    if not isfirefoxrepo(srcrepo):
        return res

    if args:
        dest = args[0]
    elif 'dest' in kwargs:
        dest = kwargs['dest']
    else:
        dest = None

    if not dest:
        dest = hg.defaultdest(source)
    else:
        dest = ui.expandpath(dest)

    try:
        from mercurial.vfs import vfs
    except ImportError:
        vfs = scmutil.vfs

    destwvfs = vfs(dest, realpath=True)
    r = hg.repository(ui, destwvfs.base)

    with r.wlock():
        with r.vfs('shared', 'ab') as fh:
            fh.write('firefoxtrees\n')

    return res
Example #43
0
def get_outgoing_bfiles(ui, repo, dest=None, **opts):
    dest = ui.expandpath(dest or 'default-push', dest or 'default')
    dest, branches = hg.parseurl(dest, opts.get('branch'))
    revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
    if revs:
        revs = [repo.lookup(rev) for rev in revs]

    # Mercurial <= 1.5 had remoteui in cmdutil, then it moved to hg
    try:
        remoteui = cmdutil.remoteui
    except AttributeError:
        remoteui = hg.remoteui

    try:
        remote = hg.repository(remoteui(repo, opts), dest)
    except error.RepoError:
        return None
    o = bfutil.findoutgoing(repo, remote, False)
    if not o:
        return None
    o = repo.changelog.nodesbetween(o, revs)[0]
    if opts.get('newest_first'):
        o.reverse()

    toupload = set()
    for n in o:
        parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
        ctx = repo[n]
        files = set(ctx.files())
        if len(parents) == 2:
            mc = ctx.manifest()
            mp1 = ctx.parents()[0].manifest()
            mp2 = ctx.parents()[1].manifest()
            for f in mp1:
                if f not in mc:
                        files.add(f)
            for f in mp2:
                if f not in mc:
                    files.add(f)
            for f in mc:
                if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
                    files.add(f)
        toupload = toupload.union(set([f for f in files if bfutil.is_standin(f) and f in ctx]))
    return toupload
Example #44
0
def share(orig, ui, source, *args, **kwargs):
    """Wraps hg.share to mark the firefoxtrees file as shared.

    The .hg/shared file lists things that are shared. We add firefoxtrees
    to it if we are a Firefox repo.
    """
    res = orig(ui, source, *args, **kwargs)

    if not util.safehasattr(source, 'local'):
        origsource = ui.expandpath(source)
        source, branches = hg.parseurl(origsource)
        srcrepo = hg.repository(ui, source)
    else:
        srcrepo = source.local()

    if not isfirefoxrepo(srcrepo):
        return res

    if args:
        dest = args[0]
    elif 'dest' in kwargs:
        dest = kwargs['dest']
    else:
        dest = None

    if not dest:
        dest = hg.defaultdest(source)
    else:
        dest = ui.expandpath(dest)

    try:
        from mercurial.vfs import vfs
    except ImportError:
        vfs = scmutil.vfs

    destwvfs = vfs(dest, realpath=True)
    r = hg.repository(ui, destwvfs.base)

    with r.wlock():
        with r.vfs(b'shared', b'ab') as fh:
            fh.write(b'firefoxtrees\n')

    return res
Example #45
0
def taskspush(orig, ui, repo, dest=None, **opts):
    ''' Task push
    Calls custom push command with new custom args'''
    # all copied from mercurial/commands.py
    dest, revs, checkout = hg.parseurl(
        ui.expandpath(dest or 'default-push', dest or 'default'),
        opts.get('rev'))
    cmdutil.setremoteconfig(ui, opts)

    other = hg.repository(ui, dest)
    ui.status(_('pushing to %s\n') % url.hidepassword(dest))
    if revs:
        revs = [repo.lookup(rev) for rev in revs]
    # add in our new options
    r = repo.push(other,
                  opts.get('force'),
                  revs=revs,
                  completed_tasks=opts.get('completed_tasks'),
                  all_tasks=opts.get('all_tasks'))
    return r == 0
Example #46
0
    def testparse(self):

        self.assertEqual(hg.parseurl(b'http://example.com/no/anchor'),
                         (b'http://example.com/no/anchor', (None, [])))
        self.assertEqual(hg.parseurl(b'http://example.com/an/anchor#foo'),
                         (b'http://example.com/an/anchor', (b'foo', [])))
        self.assertEqual(
            hg.parseurl(b'http://example.com/no/anchor/branches', [b'foo']),
            (b'http://example.com/no/anchor/branches', (None, [b'foo'])))
        self.assertEqual(
            hg.parseurl(b'http://example.com/an/anchor/branches#bar',
                        [b'foo']),
            (b'http://example.com/an/anchor/branches', (b'bar', [b'foo'])))
        self.assertEqual(
            hg.parseurl(b'http://example.com/an/anchor/branches-None#foo',
                        None),
            (b'http://example.com/an/anchor/branches-None', (b'foo', [])))
        self.assertEqual(hg.parseurl(b'http://example.com/'),
                         (b'http://example.com/', (None, [])))
        self.assertEqual(hg.parseurl(b'http://example.com'),
                         (b'http://example.com/', (None, [])))
        self.assertEqual(hg.parseurl(b'http://example.com#foo'),
                         (b'http://example.com/', (b'foo', [])))
Example #47
0
def findoutgoing(ui, repo, remote=None, force=False, opts={}):
    """utility function to find the first outgoing changeset

    Used by initialisation code"""
    dest = ui.expandpath(remote or 'default-push', remote or 'default')
    dest, revs = hg.parseurl(dest, None)[:2]
    ui.status(_('comparing with %s\n') % util.hidepassword(dest))

    revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
    other = hg.peer(repo, opts, dest)

    if revs:
        revs = [repo.lookup(rev) for rev in revs]

    # hexlify nodes from outgoing, because we're going to parse
    # parent[0] using revsingle below, and if the binary hash
    # contains special revset characters like ":" the revset
    # parser can choke.
    outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
    if not outgoing.missing:
        raise util.Abort(_('no outgoing ancestors'))
    return outgoing.missing[0]
Example #48
0
def getoutgoinglfiles(ui, repo, dest=None, **opts):
    dest = ui.expandpath(dest or 'default-push', dest or 'default')
    dest, branches = hg.parseurl(dest, opts.get('branch'))
    revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
    if revs:
        revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]

    try:
        remote = hg.peer(repo, opts, dest)
    except error.RepoError:
        return None
    outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
    if not outgoing.missing:
        return outgoing.missing
    o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
    if opts.get('newest_first'):
        o.reverse()

    toupload = set()
    for n in o:
        parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
        ctx = repo[n]
        files = set(ctx.files())
        if len(parents) == 2:
            mc = ctx.manifest()
            mp1 = ctx.parents()[0].manifest()
            mp2 = ctx.parents()[1].manifest()
            for f in mp1:
                if f not in mc:
                    files.add(f)
            for f in mp2:
                if f not in mc:
                    files.add(f)
            for f in mc:
                if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
                    files.add(f)
        toupload = toupload.union(
            set([f for f in files if lfutil.isstandin(f) and f in ctx]))
    return sorted(toupload)
Example #49
0
def remotemarkers(ui, repo, source, opts):
    # Disable status output from fetching a remote.
    ui.quiet = True

    markers = []

    source, branches = hg.parseurl(ui.expandpath(source))
    remote = hg.peer(repo, opts, source)

    with remote.commandexecutor() as e:
        branchmap = e.callcommand(b'branchmap', {}).result()

    for branch_name in branchmap:
        for branch_node in branchmap[branch_name]:
            markers.append({
                'type': 'branch',
                'name': branch_name,
                'node': node.hex(branch_node),
                'description': None,
            })

    with remote.commandexecutor() as e:
        remotemarks = bookmarks.unhexlifybookmarks(
            e.callcommand(b'listkeys', {
                b'namespace': b'bookmarks',
            }).result())

    for mark in remotemarks:
        markers.append({
            'type': 'bookmark',
            'name': mark,
            'node': node.hex(remotemarks[mark]),
            'description': None,
        })

    return markers
Example #50
0
def diff(orig, ui, repo, *pats, **opts):
    """
    [rdiff]
    If the first argument to the diff command is a remote repository URL,
    the diff will be performed against that URL. If revision arguments are
    given, the first revision is the revision in the source repository,
    and the second revision is looked up in the destination.
    
    The --reverse flag cause the direction of the diff to be reversed.
    """
    url = None
    rrev = None
    if pats:
        path = ui.expandpath(pats[0])
        if hasattr(hg, 'parseurl'):
            args = hg.parseurl(ui.expandpath(pats[0]), [])
            # parseurl changed from returning two args to three
            path, rrev = args[0], args[-1]
            # 1.6 (3d6915f5a2bb): parseurl returns (url, (branch, branches))
            if type(rrev) == tuple:
                rrev = rrev[0]
        if '://' in path or os.path.isdir(os.path.join(path, '.hg')):
            url = path
            pats = pats[1:]

    if url:
        lrev = None
        if len(opts['rev']) > 2 or rrev and len(opts['rev']) > 1:
            raise util.Abort(_('too many revisions'))
        if opts['rev']:
            lrev = opts['rev'][0]
        if len(opts['rev']) > 1:
            rrev = opts['rev'][1]
        return rdiff(ui, repo, url, lrev, rrev, *pats, **opts)
    else:
        return orig(ui, repo, *pats, **opts)
Example #51
0
def testparse(url, rev=[]):
    print '%s, revs: %r, checkout: %r' % parseurl(url, rev)
Example #52
0
def trackedcmd(ui, repo, remotepath=None, *pats, **opts):
    """show or change the current narrowspec

    With no argument, shows the current narrowspec entries, one per line. Each
    line will be prefixed with 'I' or 'X' for included or excluded patterns,
    respectively.

    The narrowspec is comprised of expressions to match remote files and/or
    directories that should be pulled into your client.
    The narrowspec has *include* and *exclude* expressions, with excludes always
    trumping includes: that is, if a file matches an exclude expression, it will
    be excluded even if it also matches an include expression.
    Excluding files that were never included has no effect.

    Each included or excluded entry is in the format described by
    'hg help patterns'.

    The options allow you to add or remove included and excluded expressions.

    If --clear is specified, then all previous includes and excludes are DROPPED
    and replaced by the new ones specified to --addinclude and --addexclude.
    If --clear is specified without any further options, the narrowspec will be
    empty and will not match any files.
    """
    opts = pycompat.byteskwargs(opts)
    if repository.NARROW_REQUIREMENT not in repo.requirements:
        ui.warn(_('The narrow command is only supported on respositories cloned'
                  ' with --narrow.\n'))
        return 1

    # Before supporting, decide whether it "hg tracked --clear" should mean
    # tracking no paths or all paths.
    if opts['clear']:
        ui.warn(_('The --clear option is not yet supported.\n'))
        return 1

    # import rules from a file
    newrules = opts.get('import_rules')
    if newrules:
        try:
            filepath = os.path.join(encoding.getcwd(), newrules)
            fdata = util.readfile(filepath)
        except IOError as inst:
            raise error.Abort(_("cannot read narrowspecs from '%s': %s") %
                              (filepath, encoding.strtolocal(inst.strerror)))
        includepats, excludepats, profiles = sparse.parseconfig(ui, fdata,
                                                                'narrow')
        if profiles:
            raise error.Abort(_("including other spec files using '%include' "
                                "is not supported in narrowspec"))
        opts['addinclude'].extend(includepats)
        opts['addexclude'].extend(excludepats)

    addedincludes = narrowspec.parsepatterns(opts['addinclude'])
    removedincludes = narrowspec.parsepatterns(opts['removeinclude'])
    addedexcludes = narrowspec.parsepatterns(opts['addexclude'])
    removedexcludes = narrowspec.parsepatterns(opts['removeexclude'])

    only_show = not (addedincludes or removedincludes or addedexcludes or
                     removedexcludes or newrules)

    oldincludes, oldexcludes = repo.narrowpats

    # filter the user passed additions and deletions into actual additions and
    # deletions of excludes and includes
    addedincludes -= oldincludes
    removedincludes &= oldincludes
    addedexcludes -= oldexcludes
    removedexcludes &= oldexcludes

    widening = addedincludes or removedexcludes
    narrowing = removedincludes or addedexcludes

    # Only print the current narrowspec.
    if only_show:
        ui.pager('tracked')
        fm = ui.formatter('narrow', opts)
        for i in sorted(oldincludes):
            fm.startitem()
            fm.write('status', '%s ', 'I', label='narrow.included')
            fm.write('pat', '%s\n', i, label='narrow.included')
        for i in sorted(oldexcludes):
            fm.startitem()
            fm.write('status', '%s ', 'X', label='narrow.excluded')
            fm.write('pat', '%s\n', i, label='narrow.excluded')
        fm.end()
        return 0

    if not widening and not narrowing:
        ui.status(_("nothing to widen or narrow\n"))
        return 0

    with repo.wlock(), repo.lock():
        cmdutil.bailifchanged(repo)

        # Find the revisions we have in common with the remote. These will
        # be used for finding local-only changes for narrowing. They will
        # also define the set of revisions to update for widening.
        remotepath = ui.expandpath(remotepath or 'default')
        url, branches = hg.parseurl(remotepath)
        ui.status(_('comparing with %s\n') % util.hidepassword(url))
        remote = hg.peer(repo, opts, url)

        # check narrow support before doing anything if widening needs to be
        # performed. In future we should also abort if client is ellipses and
        # server does not support ellipses
        if widening and wireprototypes.NARROWCAP not in remote.capabilities():
            raise error.Abort(_("server does not support narrow clones"))

        commoninc = discovery.findcommonincoming(repo, remote)

        if narrowing:
            newincludes = oldincludes - removedincludes
            newexcludes = oldexcludes | addedexcludes
            _narrow(ui, repo, remote, commoninc, oldincludes, oldexcludes,
                    newincludes, newexcludes,
                    opts['force_delete_local_changes'])
            # _narrow() updated the narrowspec and _widen() below needs to
            # use the updated values as its base (otherwise removed includes
            # and addedexcludes will be lost in the resulting narrowspec)
            oldincludes = newincludes
            oldexcludes = newexcludes

        if widening:
            newincludes = oldincludes | addedincludes
            newexcludes = oldexcludes - removedexcludes
            _widen(ui, repo, remote, commoninc, oldincludes, oldexcludes,
                    newincludes, newexcludes)

    return 0
Example #53
0
def trackedcmd(ui, repo, remotepath=None, *pats, **opts):
    """show or change the current narrowspec

    With no argument, shows the current narrowspec entries, one per line. Each
    line will be prefixed with 'I' or 'X' for included or excluded patterns,
    respectively.

    The narrowspec is comprised of expressions to match remote files and/or
    directories that should be pulled into your client.
    The narrowspec has *include* and *exclude* expressions, with excludes always
    trumping includes: that is, if a file matches an exclude expression, it will
    be excluded even if it also matches an include expression.
    Excluding files that were never included has no effect.

    Each included or excluded entry is in the format described by
    'hg help patterns'.

    The options allow you to add or remove included and excluded expressions.

    If --clear is specified, then all previous includes and excludes are DROPPED
    and replaced by the new ones specified to --addinclude and --addexclude.
    If --clear is specified without any further options, the narrowspec will be
    empty and will not match any files.

    If --auto-remove-includes is specified, then those includes that don't match
    any files modified by currently visible local commits (those not shared by
    the remote) will be added to the set of explicitly specified includes to
    remove.

    --import-rules accepts a path to a file containing rules, allowing you to
    add --addinclude, --addexclude rules in bulk. Like the other include and
    exclude switches, the changes are applied immediately.
    """
    opts = pycompat.byteskwargs(opts)
    if repository.NARROW_REQUIREMENT not in repo.requirements:
        raise error.Abort(
            _(b'the tracked command is only supported on '
              b'repositories cloned with --narrow'))

    # Before supporting, decide whether it "hg tracked --clear" should mean
    # tracking no paths or all paths.
    if opts[b'clear']:
        raise error.Abort(_(b'the --clear option is not yet supported'))

    # import rules from a file
    newrules = opts.get(b'import_rules')
    if newrules:
        try:
            filepath = os.path.join(encoding.getcwd(), newrules)
            fdata = util.readfile(filepath)
        except IOError as inst:
            raise error.Abort(
                _(b"cannot read narrowspecs from '%s': %s") %
                (filepath, encoding.strtolocal(inst.strerror)))
        includepats, excludepats, profiles = sparse.parseconfig(
            ui, fdata, b'narrow')
        if profiles:
            raise error.Abort(
                _(b"including other spec files using '%include' "
                  b"is not supported in narrowspec"))
        opts[b'addinclude'].extend(includepats)
        opts[b'addexclude'].extend(excludepats)

    addedincludes = narrowspec.parsepatterns(opts[b'addinclude'])
    removedincludes = narrowspec.parsepatterns(opts[b'removeinclude'])
    addedexcludes = narrowspec.parsepatterns(opts[b'addexclude'])
    removedexcludes = narrowspec.parsepatterns(opts[b'removeexclude'])
    autoremoveincludes = opts[b'auto_remove_includes']

    update_working_copy = opts[b'update_working_copy']
    only_show = not (addedincludes or removedincludes or addedexcludes
                     or removedexcludes or newrules or autoremoveincludes
                     or update_working_copy)

    oldincludes, oldexcludes = repo.narrowpats

    # filter the user passed additions and deletions into actual additions and
    # deletions of excludes and includes
    addedincludes -= oldincludes
    removedincludes &= oldincludes
    addedexcludes -= oldexcludes
    removedexcludes &= oldexcludes

    widening = addedincludes or removedexcludes
    narrowing = removedincludes or addedexcludes

    # Only print the current narrowspec.
    if only_show:
        ui.pager(b'tracked')
        fm = ui.formatter(b'narrow', opts)
        for i in sorted(oldincludes):
            fm.startitem()
            fm.write(b'status', b'%s ', b'I', label=b'narrow.included')
            fm.write(b'pat', b'%s\n', i, label=b'narrow.included')
        for i in sorted(oldexcludes):
            fm.startitem()
            fm.write(b'status', b'%s ', b'X', label=b'narrow.excluded')
            fm.write(b'pat', b'%s\n', i, label=b'narrow.excluded')
        fm.end()
        return 0

    if update_working_copy:
        with repo.wlock(), repo.lock(), repo.transaction(b'narrow-wc'):
            narrowspec.updateworkingcopy(repo)
            narrowspec.copytoworkingcopy(repo)
        return 0

    if not (widening or narrowing or autoremoveincludes):
        ui.status(_(b"nothing to widen or narrow\n"))
        return 0

    with repo.wlock(), repo.lock():
        cmdutil.bailifchanged(repo)

        # Find the revisions we have in common with the remote. These will
        # be used for finding local-only changes for narrowing. They will
        # also define the set of revisions to update for widening.
        remotepath = ui.expandpath(remotepath or b'default')
        url, branches = hg.parseurl(remotepath)
        ui.status(_(b'comparing with %s\n') % util.hidepassword(url))
        remote = hg.peer(repo, opts, url)

        # check narrow support before doing anything if widening needs to be
        # performed. In future we should also abort if client is ellipses and
        # server does not support ellipses
        if widening and wireprototypes.NARROWCAP not in remote.capabilities():
            raise error.Abort(_(b"server does not support narrow clones"))

        commoninc = discovery.findcommonincoming(repo, remote)

        if autoremoveincludes:
            outgoing = discovery.findcommonoutgoing(repo,
                                                    remote,
                                                    commoninc=commoninc)
            ui.status(_(b'looking for unused includes to remove\n'))
            localfiles = set()
            for n in itertools.chain(outgoing.missing, outgoing.excluded):
                localfiles.update(repo[n].files())
            suggestedremovals = []
            for include in sorted(oldincludes):
                match = narrowspec.match(repo.root, [include], oldexcludes)
                if not any(match(f) for f in localfiles):
                    suggestedremovals.append(include)
            if suggestedremovals:
                for s in suggestedremovals:
                    ui.status(b'%s\n' % s)
                if (ui.promptchoice(
                        _(b'remove these unused includes (yn)?'
                          b'$$ &Yes $$ &No')) == 0):
                    removedincludes.update(suggestedremovals)
                    narrowing = True
            else:
                ui.status(_(b'found no unused includes\n'))

        if narrowing:
            newincludes = oldincludes - removedincludes
            newexcludes = oldexcludes | addedexcludes
            _narrow(
                ui,
                repo,
                remote,
                commoninc,
                oldincludes,
                oldexcludes,
                newincludes,
                newexcludes,
                opts[b'force_delete_local_changes'],
            )
            # _narrow() updated the narrowspec and _widen() below needs to
            # use the updated values as its base (otherwise removed includes
            # and addedexcludes will be lost in the resulting narrowspec)
            oldincludes = newincludes
            oldexcludes = newexcludes

        if widening:
            newincludes = oldincludes | addedincludes
            newexcludes = oldexcludes - removedexcludes
            _widen(
                ui,
                repo,
                remote,
                commoninc,
                oldincludes,
                oldexcludes,
                newincludes,
                newexcludes,
            )

    return 0
Example #54
0
def parseurl(url, heads=[]):
    checkout = None
    svn_url, (_junk, heads) = hg.parseurl(url, heads)
    if heads:
        checkout = heads[0]
    return svn_url, heads, checkout
Example #55
0
def histedit(ui, repo, *parent, **opts):
    """hg histedit <parent>
    """
    # TODO only abort if we try and histedit mq patches, not just
    # blanket if mq patches are applied somewhere
    mq = getattr(repo, 'mq', None)
    if mq and mq.applied:
        raise util.Abort(_('source has mq patches applied'))

    parent = list(parent) + opts.get('rev', [])
    if opts.get('outgoing'):
        if len(parent) > 1:
            raise util.Abort('only one repo argument allowed with --outgoing')
        elif parent:
            parent = parent[0]

        dest = ui.expandpath(parent or 'default-push', parent or 'default')
        dest, revs = hg.parseurl(dest, None)[:2]
        if isinstance(revs, tuple):
            # hg >= 1.6
            revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
            other = hg.repository(hg.remoteui(repo, opts), dest)
            # hg >= 1.9
            findoutgoing = getattr(discovery, 'findoutgoing', None)
            if findoutgoing is None:
                if getattr(discovery, 'outgoing', None) is not None:

                    def findoutgoing(repo, other, force=False):
                        out = discovery.findcommonoutgoing(repo,
                                                           other, [],
                                                           force=force)
                        return out.missing[0:1]
                else:
                    # hg 1.9 and 2.0
                    def findoutgoing(repo, other, force=False):
                        common, outheads = discovery.findcommonoutgoing(
                            repo, other, [], force=force)
                        return repo.changelog.findmissing(common,
                                                          outheads)[0:1]
        else:
            other = hg.repository(ui, dest)

            def findoutgoing(repo, other, force=False):
                return repo.findoutgoing(other, force=force)

        if revs:
            revs = [repo.lookup(rev) for rev in revs]

        ui.status(_('comparing with %s\n') % hidepassword(dest))
        parent = findoutgoing(repo, other, force=opts.get('force'))
    else:
        if opts.get('force'):
            raise util.Abort('--force only allowed with --outgoing')

    if opts.get('continue', False):
        if len(parent) != 0:
            raise util.Abort('no arguments allowed with --continue')
        (
            parentctxnode,
            created,
            replaced,
            tmpnodes,
            existing,
            rules,
            keep,
            tip,
        ) = readstate(repo)
        currentparent, wantnull = repo.dirstate.parents()
        parentctx = repo[parentctxnode]
        # discover any nodes the user has added in the interim
        newchildren = [
            c for c in parentctx.children() if c.node() not in existing
        ]
        action, currentnode = rules.pop(0)
        while newchildren:
            if action in [
                    'f',
                    'fold',
            ]:
                tmpnodes.extend([n.node() for n in newchildren])
            else:
                created.extend([n.node() for n in newchildren])
            newchildren = filter(
                lambda x: x.node() not in existing,
                reduce(lambda x, y: x + y,
                       map(lambda r: r.children(), newchildren)))
        m, a, r, d = repo.status()[:4]
        oldctx = repo[currentnode]
        message = oldctx.description()
        if action in ('e', 'edit', 'm', 'mess'):
            message = ui.edit(message, ui.username())
        elif action in (
                'f',
                'fold',
        ):
            message = 'fold-temp-revision %s' % currentnode
        new = None
        if m or a or r or d:
            new = repo.commit(text=message,
                              user=oldctx.user(),
                              date=oldctx.date(),
                              extra=oldctx.extra())

        if action in ('f', 'fold'):
            if new:
                tmpnodes.append(new)
            else:
                new = newchildren[-1]
            (
                parentctx,
                created_,
                replaced_,
                tmpnodes_,
            ) = finishfold(ui, repo, parentctx, oldctx, new, opts, newchildren)
            replaced.extend(replaced_)
            created.extend(created_)
            tmpnodes.extend(tmpnodes_)
        elif action not in ('d', 'drop'):
            if new != oldctx.node():
                replaced.append(oldctx.node())
            if new:
                if new != oldctx.node():
                    created.append(new)
                parentctx = repo[new]

    elif opts.get('abort', False):
        if len(parent) != 0:
            raise util.Abort('no arguments allowed with --abort')
        (
            parentctxnode,
            created,
            replaced,
            tmpnodes,
            existing,
            rules,
            keep,
            tip,
        ) = readstate(repo)
        ui.debug('restore wc to old tip %s\n' % node.hex(tip))
        hg.clean(repo, tip)
        ui.debug('should strip created nodes %s\n' %
                 ', '.join([node.hex(n)[:12] for n in created]))
        ui.debug('should strip temp nodes %s\n' %
                 ', '.join([node.hex(n)[:12] for n in tmpnodes]))
        for nodes in (
                created,
                tmpnodes,
        ):
            for n in reversed(nodes):
                try:
                    repair.strip(ui, repo, n)
                except error.LookupError:
                    pass
        os.unlink(os.path.join(repo.path, 'histedit-state'))
        return
    else:
        bailifchanged(repo)
        if os.path.exists(os.path.join(repo.path, 'histedit-state')):
            raise util.Abort('history edit already in progress, try '
                             '--continue or --abort')

        tip, empty = repo.dirstate.parents()

        if len(parent) != 1:
            raise util.Abort('requires exactly one parent revision')
        parent = _revsingle(repo, parent[0]).node()

        keep = opts.get('keep', False)
        revs = between(repo, parent, tip, keep)

        ctxs = [repo[r] for r in revs]
        existing = [r.node() for r in ctxs]
        rules = opts.get('commands', '')
        if not rules:
            rules = '\n'.join([makedesc(c) for c in ctxs])
            rules += editcomment % (
                node.hex(parent)[:12],
                node.hex(tip)[:12],
            )
            rules = ui.edit(rules, ui.username())
            # Save edit rules in .hg/histedit-last-edit.txt in case
            # the user needs to ask for help after something
            # surprising happens.
            f = open(repo.join('histedit-last-edit.txt'), 'w')
            f.write(rules)
            f.close()
        else:
            f = open(rules)
            rules = f.read()
            f.close()
        rules = [
            l for l in (r.strip() for r in rules.splitlines())
            if l and not l[0] == '#'
        ]
        rules = verifyrules(rules, repo, ctxs)

        parentctx = repo[parent].parents()[0]
        keep = opts.get('keep', False)
        replaced = []
        tmpnodes = []
        created = []

    while rules:
        writestate(repo, parentctx.node(), created, replaced, tmpnodes,
                   existing, rules, keep, tip)
        action, ha = rules.pop(0)
        (
            parentctx,
            created_,
            replaced_,
            tmpnodes_,
        ) = actiontable[action](ui, repo, parentctx, ha, opts)
        created.extend(created_)
        replaced.extend(replaced_)
        tmpnodes.extend(tmpnodes_)

    hg.update(repo, parentctx.node())

    if not keep:
        ui.debug('should strip replaced nodes %s\n' %
                 ', '.join([node.hex(n)[:12] for n in replaced]))
        for n in sorted(replaced,
                        lambda x, y: cmp(repo[x].rev(), repo[y].rev())):
            try:
                repair.strip(ui, repo, n)
            except error.LookupError:
                pass

    ui.debug('should strip temp nodes %s\n' %
             ', '.join([node.hex(n)[:12] for n in tmpnodes]))
    for n in reversed(tmpnodes):
        try:
            repair.strip(ui, repo, n)
        except error.LookupError:
            pass
    os.unlink(os.path.join(repo.path, 'histedit-state'))
Example #56
0
def parseurl(source):
    '''wrap hg.parseurl to work on 1.3 -> 1.5'''
    return hg.parseurl(source, None)[:2]