diff --git a/hggit/__init__.py b/hggit/__init__.py index a0d2a9bc6e1472f52dc5904e7aca0dfa53d57bde_aGdnaXQvX19pbml0X18ucHk=..765c596aff847a1bae9db1f60ed61a95a0ad7913_aGdnaXQvX19pbml0X18ucHk= 100644 --- a/hggit/__init__.py +++ b/hggit/__init__.py @@ -130,6 +130,7 @@ from . import overlay from . import revsets from . import schemes +from . import templates from . import util from mercurial.node import bin @@ -160,7 +161,7 @@ cmdtable = commands.cmdtable configtable = {} configitem = registrar.configitem(configtable) -templatekeyword = registrar.templatekeyword() +templatekeyword = templates.templatekeyword compat.registerconfigs(configitem) @@ -308,20 +309,3 @@ extensions.wrapfunction(exchange, b'push', exchangepush) - -def _gitnodekw(node, repo): - if not hasattr(repo, 'githandler'): - return None - gitnode = repo.githandler.map_git_get(node.hex()) - if gitnode is None: - gitnode = b'' - return gitnode - - -@templatekeyword(b'gitnode', requires={b'ctx', b'repo'}) -def gitnodekw(context, mapping): - """:gitnode: String. The Git changeset identification hash, as a - 40 hexadecimal digit string.""" - node = context.resource(mapping, b'ctx') - repo = context.resource(mapping, b'repo') - return _gitnodekw(node, repo) diff --git a/hggit/__init__.py b/hggit/templates.py similarity index 14% copy from hggit/__init__.py copy to hggit/templates.py index a0d2a9bc6e1472f52dc5904e7aca0dfa53d57bde_aGdnaXQvX19pbml0X18ucHk=..765c596aff847a1bae9db1f60ed61a95a0ad7913_aGdnaXQvdGVtcGxhdGVzLnB5 100644 --- a/hggit/__init__.py +++ b/hggit/templates.py @@ -6,118 +6,5 @@ # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. -r'''push and pull from a Git server - -This extension lets you communicate (push and pull) with a Git server. -This way you can use Git hosting for your project or collaborate with a -project that is in Git. A bridger of worlds, this plugin be. - -Try :hg:`clone git+https://github.com/dulwich/dulwich` or :hg:`clone -git+ssh://example.com/repo.git`. - -Basic Use ---------- - -You can clone a Git repository from Mercurial by running :hg:`clone -<url> [dest]`. For example, if you were to run:: - - $ hg clone git://github.com/schacon/hg-git.git - -Hg-Git would clone the repository and convert it to a Mercurial repository for -you. There are a number of different protocols that can be used for Git -repositories. Examples of Git repository URLs include:: - - git+https://github.com/hg-git/hg-git.git - git+http://github.com/hg-git/hg-git.git - git+ssh://git@github.com/hg-git/hg-git.git - git://github.com/hg-git/hg-git.git - file:///path/to/hg-git - ../hg-git (local file path) - -These also work:: - - git+ssh://git@github.com:hg-git/hg-git.git - git@github.com:hg-git/hg-git.git - -Please note that you need to prepend HTTP, HTTPS, and SSH URLs with -``git+`` in order differentiate them from Mercurial URLs. For example, -an HTTPS URL would start with ``git+https://``. Also, note that Git -doesn't require the specification of the protocol for SSH, but -Mercurial does. Hg-Git automatically detects whether file paths should -be treated as Git repositories by their contents. - -If you are starting from an existing Mercurial repository, you have to -set up a Git repository somewhere that you have push access to, add a -path entry for it in your .hg/hgrc file, and then run :hg:`push -[name]` from within your repository. For example:: - - $ cd hg-git # (a Mercurial repository) - $ # edit .hg/hgrc and add the target Git URL in the paths section - $ hg push - -This will convert all your Mercurial changesets into Git objects and push -them to the Git server. - -Pulling new revisions into a repository is the same as from any other -Mercurial source. Within the earlier examples, the following commands are -all equivalent:: - - $ hg pull - $ hg pull default - $ hg pull git://github.com/hg-git/hg-git.git - -Git branches are exposed in Mercurial as bookmarks, while Git remote -branches are exposed as unchangable Mercurial local tags. See -:hg:`help bookmarks` and :hg:`help tags` for further information. - -Finding and displaying Git revisions ------------------------------------- - -For displaying the Git revision ID, Hg-Git provides a template keyword: - - :gitnode: String. The Git changeset identification hash, as a 40 hexadecimal - digit string. - -For example:: - - $ hg log --template='{rev}:{node|short}:{gitnode|short} {desc}\n' - $ hg log --template='hg: {node}\ngit: {gitnode}\n{date|isodate} {author}\n{desc}\n\n' - -For finding changesets from Git, Hg-Git extends revsets to provide two new -selectors: - - :fromgit: Select changesets that originate from Git. Takes no arguments. - :gitnode: Select changesets that originate in a specific Git revision. Takes - a revision argument. - -For example:: - - $ hg log -r 'fromgit()' - $ hg log -r 'gitnode(84f75b909fc3)' - -Revsets are accepted by several Mercurial commands for specifying -revisions. See :hg:`help revsets` for details. - -Invalid and dangerous paths ---------------------------- - -Both Mercurial and Git consider paths as just bytestrings internally, -and allow almost anything. The difference, however, is in the _almost_ -part. For example, many Git servers will reject a push for security -reasons if it contains a nested Git repository. Similarly, Mercurial -cannot checkout commits with a nested repository, and it cannot even -store paths containing an embedded newline or carrage return -character. - -The default is to issue a warning and skip these paths. You can -change this by setting ``hggit.invalidpaths`` in :hg:`config`:: - - [hggit] - invalidpaths = keep - -Possible values are ``keep``, ``skip`` or ``abort``. - -''' - from __future__ import generator_stop @@ -122,92 +9,4 @@ from __future__ import generator_stop -# local modules -from . import commands -from . import compat -from . import gitrepo -from . import git_handler -from . import hgrepo -from . import overlay -from . import revsets -from . import schemes -from . import util - -from mercurial.node import bin -from mercurial import ( - bundlerepo, - demandimport, - dirstate, - discovery, - exchange, - extensions, - hg, - manifest, - pycompat, - registrar, - repoview, -) - -demandimport.IGNORES |= { - b'collections', -} - -__version__ = b'0.11.0dev' - -testedwith = (b'5.2 5.3 5.4 5.5 5.6 5.7 5.8') -minimumhgversion = b'5.2' -buglink = b'https://foss.heptapod.net/mercurial/hg-git/issues' - -cmdtable = commands.cmdtable -configtable = {} -configitem = registrar.configitem(configtable) -templatekeyword = registrar.templatekeyword() - -compat.registerconfigs(configitem) - - -def getversion(): - """return version with dependencies for hg --version -v""" - import dulwich - dulver = b'.'.join(pycompat.sysbytes(str(i)) for i in dulwich.__version__) - return __version__ + (b" (dulwich %s)" % dulver) - - -# defend against tracebacks if we specify -r in 'hg pull' -def safebranchrevs(orig, lrepo, otherrepo, branches, revs): - revs, co = orig(lrepo, otherrepo, branches, revs) - if isinstance(otherrepo, gitrepo.gitrepo): - # FIXME: Unless it's None, the 'co' result is passed to the lookup() - # remote command. Since our implementation of the lookup() remote - # command is incorrect, we set it to None to avoid a crash later when - # the incorect result of the lookup() remote command would otherwise be - # used. This can, in undocumented corner-cases, result in that a - # different revision is updated to when passing both -u and -r to - # 'hg pull'. An example of such case is in tests/test-addbranchrevs.t - # (for the non-hg-git case). - co = None - return revs, co -extensions.wrapfunction(hg, b'addbranchrevs', safebranchrevs) - - -def extsetup(ui): - commands.extsetup(ui) - revsets.extsetup(ui) - schemes.extsetup(ui) - - -def reposetup(ui, repo): - if not isinstance(repo, gitrepo.gitrepo): - if (getattr(dirstate, 'rootcache', False) and - git_handler.has_gitrepo(repo)): - # only install our dirstate wrapper if it has a hope of working - from . import gitdirstate - dirstate.dirstate = gitdirstate.gitdirstate - - klass = hgrepo.generate_repo_subclass(repo.__class__) - repo.__class__ = klass - - -extensions.wrapfunction(manifest.manifestdict, b'diff', - overlay.wrapmanifestdictdiff) - +from mercurial import registrar @@ -213,100 +12,5 @@ -def findcommonoutgoing(orig, repo, other, *args, **kwargs): - if isinstance(other, gitrepo.gitrepo): - heads = repo.githandler.get_refs(other.path)[0] - kw = {} - kw.update(kwargs) - for val, k in zip(args, - ('onlyheads', 'force', 'commoninc', 'portable')): - kw[k] = val - force = kw.get('force', False) - commoninc = kw.get('commoninc', None) - if commoninc is None: - commoninc = discovery.findcommonincoming(repo, other, heads=heads, - force=force) - kw['commoninc'] = commoninc - return orig(repo, other, **kw) - return orig(repo, other, *args, **kwargs) - - -extensions.wrapfunction(discovery, b'findcommonoutgoing', findcommonoutgoing) - - -def getremotechanges(orig, ui, repo, other, *args, **opts): - if isinstance(other, gitrepo.gitrepo): - if args: - revs = args[0] - else: - revs = opts.get('onlyheads', opts.get('revs')) - r, c, cleanup = repo.githandler.getremotechanges(other, revs) - # ugh. This is ugly even by mercurial API compatibility standards - if 'onlyheads' not in orig.__code__.co_varnames: - cleanup = None - return r, c, cleanup - return orig(ui, repo, other, *args, **opts) - - -extensions.wrapfunction(bundlerepo, b'getremotechanges', getremotechanges) - - -def pinnedrevs(orig, repo): - pinned = orig(repo) - - # Mercurial pins bookmarks, even if obsoleted, so that they always - # appear in e.g. log; do the same with git tags and remotes. - if repo.local() and hasattr(repo, 'githandler'): - rev = repo.changelog.rev - - pinned.update(rev(bin(r)) for r in repo.githandler.tags.values()) - pinned.update(rev(r) for r in repo.githandler.remote_refs.values()) - - return pinned - -extensions.wrapfunction(repoview, b'pinnedrevs', pinnedrevs) - - -@util.transform_notgit -def exchangepull(orig, repo, remote, heads=None, force=False, bookmarks=(), - **kwargs): - if isinstance(remote, gitrepo.gitrepo): - pullop = exchange.pulloperation(repo, remote, heads, force, - bookmarks=bookmarks) - pullop.trmanager = exchange.transactionmanager(repo, b'pull', - remote.url()) - - wlock = repo.wlock() - lock = repo.lock() - try: - pullop.cgresult = repo.githandler.fetch(remote.path, heads) - pullop.trmanager.close() - return pullop - finally: - pullop.trmanager.release() - lock.release() - wlock.release() - else: - return orig(repo, remote, heads, force, bookmarks=bookmarks, **kwargs) - - -extensions.wrapfunction(exchange, b'pull', exchangepull) - - -# TODO figure out something useful to do with the newbranch param -@util.transform_notgit -def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False, - bookmarks=(), opargs=None, **kwargs): - if isinstance(remote, gitrepo.gitrepo): - pushop = exchange.pushoperation(repo, remote, force, revs, newbranch, - bookmarks, - **pycompat.strkwargs(opargs or {})) - pushop.cgresult = repo.githandler.push(remote.path, revs, force) - return pushop - else: - return orig(repo, remote, force, revs, newbranch, bookmarks=bookmarks, - opargs=None, **kwargs) - - -extensions.wrapfunction(exchange, b'push', exchangepush) +templatekeyword = registrar.templatekeyword() def _gitnodekw(node, repo):