def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False, bookmarks=(), opargs=None, **kwargs): if isinstance(remote, gitrepo): pushop = exchange.pushoperation( repo, remote, force, revs, newbranch, bookmarks, **pycompat.strkwargs(opargs or {}), ) pushop.cgresult = repo.githandler.push(remote.path, revs, bookmarks, force) return pushop else: return orig( repo, remote, force, revs, newbranch, bookmarks=bookmarks, opargs=None, **kwargs, )
def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False, bookmarks=(), **kwargs): if isinstance(remote, gitrepo.gitrepo): # opargs is in Mercurial >= 3.6 opargs = kwargs.get('opargs') if opargs is None: opargs = {} pushop = exchange.pushoperation(repo, remote, force, revs, newbranch, bookmarks, **opargs) pushop.cgresult = repo.githandler.push(remote.path, revs, force) return pushop else: return orig(repo, remote, force, revs, newbranch, bookmarks=bookmarks, **kwargs)
def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False, bookmarks=(), **kwargs): capable = getattr(remote, 'capable', lambda x: False) if capable('subversion'): pushop = exchange.pushoperation(repo, remote, force, revs, newbranch, bookmarks=bookmarks) pushop.cgresult = push(repo, remote, force, revs) return pushop else: return orig(repo, remote, force, revs, newbranch, bookmarks=bookmarks, **kwargs)
def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False, bookmarks=()): if isinstance(remote, gitrepo.gitrepo): pushop = exchange.pushoperation(repo, remote, force, revs, newbranch, bookmarks) pushop.cgresult = repo.githandler.push(remote.path, revs, force) return pushop else: return orig(repo, remote, force, revs, newbranch, bookmarks=bookmarks)
def exchangepush(orig, repo, remote, force=False, revs=None, newbranch=False, bookmarks=()): capable = getattr(remote, 'capable', lambda x: False) if capable('subversion'): pushop = exchange.pushoperation(repo, remote, force, revs, newbranch, bookmarks=bookmarks) pushop.cgresult = push(repo, remote, force, revs) return pushop else: return orig(repo, remote, force, revs, newbranch, bookmarks=bookmarks)
def push(repo, dest, force, revs): """push revisions starting at a specified head back to Subversion. """ assert not revs, 'designated revisions for push remains unimplemented.' cmdutil.bailifchanged(repo) checkpush = getattr(repo, 'checkpush', None) if checkpush: try: # The checkpush function changed as of e10000369b47 (first # in 3.0) in mercurial from mercurial.exchange import pushoperation pushop = pushoperation(repo, dest, force, revs, False) checkpush(pushop) except (ImportError, TypeError): checkpush(force, revs) ui = repo.ui old_encoding = util.swap_out_encoding() try: hasobsolete = (obsolete._enabled or obsolete.isenabled(repo, obsolete.createmarkersopt)) except: hasobsolete = False temporary_commits = [] obsmarkers = [] try: # TODO: implement --rev/#rev support # TODO: do credentials specified in the URL still work? svn = dest.svn meta = repo.svnmeta(svn.uuid, svn.subdir) # Strategy: # 1. Find all outgoing commits from this head if len(repo[None].parents()) != 1: ui.status('Cowardly refusing to push branch merge\n') return 0 # results in nonzero exit status, see hg's commands.py workingrev = repo[None].parents()[0] workingbranch = workingrev.branch() ui.status('searching for changes\n') hashes = meta.revmap.hashes() outgoing = util.outgoing_revisions(repo, hashes, workingrev.node()) if not (outgoing and len(outgoing)): ui.status('no changes found\n') return 1 # so we get a sane exit status, see hg's commands.push tip_ctx = repo[outgoing[-1]].p1() svnbranch = tip_ctx.branch() modified_files = {} for i in range(len(outgoing) - 1, -1, -1): # 2. Pick the oldest changeset that needs to be pushed current_ctx = repo[outgoing[i]] original_ctx = current_ctx if len(current_ctx.parents()) != 1: ui.status('Found a branch merge, this needs discussion and ' 'implementation.\n') # results in nonzero exit status, see hg's commands.py return 0 # 3. Move the changeset to the tip of the branch if necessary conflicts = False for file in current_ctx.files(): if file in modified_files: conflicts = True break if conflicts or current_ctx.branch() != svnbranch: util.swap_out_encoding(old_encoding) try: def extrafn(ctx, extra): extra['branch'] = ctx.branch() ui.note('rebasing %s onto %s \n' % (current_ctx, tip_ctx)) hgrebase.rebase(ui, repo, dest=node.hex(tip_ctx.node()), rev=[node.hex(current_ctx.node())], extrafn=extrafn, keep=True) finally: util.swap_out_encoding() # Don't trust the pre-rebase repo and context. repo = getlocalpeer(ui, {}, meta.path) meta = repo.svnmeta(svn.uuid, svn.subdir) hashes = meta.revmap.hashes() tip_ctx = repo[tip_ctx.node()] for c in tip_ctx.descendants(): rebasesrc = c.extra().get('rebase_source') if rebasesrc and node.bin(rebasesrc) == current_ctx.node(): current_ctx = c temporary_commits.append(c.node()) break # 4. Push the changeset to subversion tip_hash = hashes[tip_ctx.node()][0] try: ui.status('committing %s\n' % current_ctx) pushedrev = pushmod.commit(ui, repo, current_ctx, meta, tip_hash, svn) except pushmod.NoFilesException: ui.warn("Could not push revision %s because it had no changes " "in svn.\n" % current_ctx) return # This hook is here purely for testing. It allows us to # onsistently trigger hit the race condition between # pushing and pulling here. In particular, we use it to # trigger another revision landing between the time we # push a revision and pull it back. repo.hook('debug-hgsubversion-between-push-and-pull-for-tests') # 5. Pull the latest changesets from subversion, which will # include the one we just committed (and possibly others). r = pull(repo, dest, force=force, meta=meta) assert not r or r == 0 # 6. Move our tip to the latest pulled tip for c in tip_ctx.descendants(): if c.node() in hashes and c.branch() == svnbranch: if meta.get_source_rev(ctx=c)[0] == pushedrev.revnum: # This is corresponds to the changeset we just pushed if hasobsolete: obsmarkers.append([(original_ctx, [c])]) tip_ctx = c # Remember what files have been modified since the # whole push started. for file in c.files(): modified_files[file] = True # 7. Rebase any children of the commit we just pushed # that are not in the outgoing set for c in original_ctx.children(): if not c.node() in hashes and not c.node() in outgoing: util.swap_out_encoding(old_encoding) try: # Path changed as subdirectories were getting # deleted during push. saved_path = os.getcwd() os.chdir(repo.root) def extrafn(ctx, extra): extra['branch'] = ctx.branch() ui.status('rebasing non-outgoing %s onto %s\n' % (c, tip_ctx)) needs_rebase_set = "%s::" % node.hex(c.node()) hgrebase.rebase(ui, repo, dest=node.hex(tip_ctx.node()), rev=[needs_rebase_set], extrafn=extrafn, keep=not hasobsolete) finally: os.chdir(saved_path) util.swap_out_encoding() util.swap_out_encoding(old_encoding) try: hg.update(repo, repo.branchtip(workingbranch)) finally: util.swap_out_encoding() with repo.wlock(): with repo.lock(): if hasobsolete: for marker in obsmarkers: obsolete.createmarkers(repo, marker) beforepush = marker[0][0] afterpush = marker[0][1][0] ui.note('marking %s as obsoleted by %s\n' % (beforepush.hex(), afterpush.hex())) else: # strip the original changesets since the push was # successful and changeset obsolescence is unavailable util.strip(ui, repo, outgoing, "all") finally: try: # It's always safe to delete the temporary commits. # The originals are not deleted unless the push # completely succeeded. if temporary_commits: # If the repo is on a temporary commit, get off before # the strip. parent = repo[None].p1() if parent.node() in temporary_commits: hg.update(repo, parent.p1().node()) with repo.wlock(): with repo.lock(): if hasobsolete: relations = ( (repo[n], ()) for n in temporary_commits) obsolete.createmarkers(repo, relations) else: util.strip( ui, repo, temporary_commits, backup=None) finally: util.swap_out_encoding(old_encoding) return 1 # so we get a sane exit status, see hg's commands.push
def push(repo, dest, force, revs): """push revisions starting at a specified head back to Subversion. """ assert not revs, 'designated revisions for push remains unimplemented.' cmdutil.bailifchanged(repo) checkpush = getattr(repo, 'checkpush', None) if checkpush: try: # The checkpush function changed as of e10000369b47 (first # in 3.0) in mercurial from mercurial.exchange import pushoperation pushop = pushoperation(repo, dest, force, revs, False) checkpush(pushop) except (ImportError, TypeError): checkpush(force, revs) ui = repo.ui old_encoding = util.swap_out_encoding() try: hasobsolete = obsolete._enabled except: hasobsolete = False temporary_commits = [] obsmarkers = [] try: # TODO: implement --rev/#rev support # TODO: do credentials specified in the URL still work? svn = dest.svn meta = repo.svnmeta(svn.uuid, svn.subdir) # Strategy: # 1. Find all outgoing commits from this head if len(repo[None].parents()) != 1: ui.status('Cowardly refusing to push branch merge\n') return 0 # results in nonzero exit status, see hg's commands.py workingrev = repo[None].parents()[0] workingbranch = workingrev.branch() ui.status('searching for changes\n') hashes = meta.revmap.hashes() outgoing = util.outgoing_revisions(repo, hashes, workingrev.node()) if not (outgoing and len(outgoing)): ui.status('no changes found\n') return 1 # so we get a sane exit status, see hg's commands.push tip_ctx = repo[outgoing[-1]].p1() svnbranch = tip_ctx.branch() modified_files = {} for i in range(len(outgoing) - 1, -1, -1): # 2. Pick the oldest changeset that needs to be pushed current_ctx = repo[outgoing[i]] original_ctx = current_ctx if len(current_ctx.parents()) != 1: ui.status('Found a branch merge, this needs discussion and ' 'implementation.\n') # results in nonzero exit status, see hg's commands.py return 0 # 3. Move the changeset to the tip of the branch if necessary conflicts = False for file in current_ctx.files(): if file in modified_files: conflicts = True break if conflicts or current_ctx.branch() != svnbranch: util.swap_out_encoding(old_encoding) try: def extrafn(ctx, extra): extra['branch'] = ctx.branch() ui.note('rebasing %s onto %s \n' % (current_ctx, tip_ctx)) hgrebase.rebase(ui, repo, dest=node.hex(tip_ctx.node()), rev=[node.hex(current_ctx.node())], extrafn=extrafn, keep=True) finally: util.swap_out_encoding() # Don't trust the pre-rebase repo and context. repo = getlocalpeer(ui, {}, meta.path) meta = repo.svnmeta(svn.uuid, svn.subdir) hashes = meta.revmap.hashes() tip_ctx = repo[tip_ctx.node()] for c in tip_ctx.descendants(): rebasesrc = c.extra().get('rebase_source') if rebasesrc and node.bin(rebasesrc) == current_ctx.node(): current_ctx = c temporary_commits.append(c.node()) break # 4. Push the changeset to subversion tip_hash = hashes[tip_ctx.node()][0] try: ui.status('committing %s\n' % current_ctx) pushedrev = pushmod.commit(ui, repo, current_ctx, meta, tip_hash, svn) except pushmod.NoFilesException: ui.warn("Could not push revision %s because it had no changes " "in svn.\n" % current_ctx) return # This hook is here purely for testing. It allows us to # onsistently trigger hit the race condition between # pushing and pulling here. In particular, we use it to # trigger another revision landing between the time we # push a revision and pull it back. repo.hook('debug-hgsubversion-between-push-and-pull-for-tests') # 5. Pull the latest changesets from subversion, which will # include the one we just committed (and possibly others). r = pull(repo, dest, force=force, meta=meta) assert not r or r == 0 # 6. Move our tip to the latest pulled tip for c in tip_ctx.descendants(): if c.node() in hashes and c.branch() == svnbranch: if meta.get_source_rev(ctx=c)[0] == pushedrev.revnum: # This is corresponds to the changeset we just pushed if hasobsolete: obsmarkers.append([(original_ctx, [c])]) tip_ctx = c # Remember what files have been modified since the # whole push started. for file in c.files(): modified_files[file] = True # 7. Rebase any children of the commit we just pushed # that are not in the outgoing set for c in original_ctx.children(): if not c.node() in hashes and not c.node() in outgoing: util.swap_out_encoding(old_encoding) try: # Path changed as subdirectories were getting # deleted during push. saved_path = os.getcwd() os.chdir(repo.root) def extrafn(ctx, extra): extra['branch'] = ctx.branch() ui.status('rebasing non-outgoing %s onto %s\n' % (c, tip_ctx)) needs_rebase_set = "%s::" % node.hex(c.node()) hgrebase.rebase(ui, repo, dest=node.hex(tip_ctx.node()), rev=[needs_rebase_set], extrafn=extrafn, keep=not hasobsolete) finally: os.chdir(saved_path) util.swap_out_encoding() util.swap_out_encoding(old_encoding) try: hg.update(repo, repo.branchtip(workingbranch)) finally: util.swap_out_encoding() if hasobsolete: for marker in obsmarkers: obsolete.createmarkers(repo, marker) beforepush = marker[0][0] afterpush = marker[0][1][0] ui.note('marking %s as obsoleted by %s\n' % (beforepush.hex(), afterpush.hex())) else: # strip the original changesets since the push was # successful and changeset obsolescence is unavailable util.strip(ui, repo, outgoing, "all") finally: try: # It's always safe to delete the temporary commits. # The originals are not deleted unless the push # completely succeeded. if temporary_commits: # If the repo is on a temporary commit, get off before # the strip. parent = repo[None].p1() if parent.node() in temporary_commits: hg.update(repo, parent.p1().node()) if hasobsolete: relations = ((repo[n], ()) for n in temporary_commits) obsolete.createmarkers(repo, relations) else: util.strip(ui, repo, temporary_commits, backup=None) finally: util.swap_out_encoding(old_encoding) return 1 # so we get a sane exit status, see hg's commands.push