def real_main(options, args): if check_for_applied_patches(): print("There are applied mq patches. Put them aside before " "running hgpullsvn.") return 1 svn_wc = "." # Get SVN info svn_info = get_svn_info('.') current_rev = svn_info['revision'] next_rev = current_rev + 1 # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted' repos_url = svn_info['repos_url'] # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted/branches/xmpp-subprotocols-2178-2' wc_url = svn_info['url'] assert wc_url.startswith(repos_url) # e.g. u'/branches/xmpp-subprotocols-2178-2' wc_base = wc_url[len(repos_url):] # e.g. 'xmpp-subprotocols-2178-2' svn_branch = wc_url.split("/")[-1] # if --branch was passed, override the branch name derived above if options.svn_branch: svn_branch = options.svn_branch if options.svn_peg: wc_url += "@" + str(options.svn_peg) # Get remote SVN info ui.status("Retrieving remote SVN info...", level=ui.VERBOSE) svn_greatest_rev = get_svn_info(wc_url)['last_changed_rev'] if svn_greatest_rev < next_rev: ui.status("No revisions after %s in SVN repo, nothing to do", svn_greatest_rev) return elif options.svn_rev != None: if options.svn_rev < next_rev: ui.status( "All revisions up to %s are already pulled in, " "nothing to do", options.svn_rev) return svn_greatest_rev = options.svn_rev # Show incoming changes if in dry-run mode. if options.dryrun: ui.status("Incoming SVN revisions:") for entry in iter_svn_log_entries(wc_url, next_rev, svn_greatest_rev, options.svnretry): if entry["message"]: msg = entry["message"].splitlines()[0].strip() else: msg = "" line = "[%d] %s (%s)" % (entry["revision"], msg, entry["author"]) ui.status(line) return # Prepare and/or switch named branches orig_branch = run_hg(["branch"]).strip() if orig_branch != svn_branch: # Update to or create the "pristine" branch if not hg_switch_branch(orig_branch, svn_branch): return 1 elif not hg_is_clean(svn_branch): return 1 # Detect that a previously aborted hgpullsvn retrieved an SVN revision # without committing it to hg. # If there is no SVN tag in current head, we may have been interrupted # during the previous "hg tag". hgsvn_rev = get_svn_rev_from_hg() if hgsvn_rev is not None and hgsvn_rev != current_rev: ui.status(("\nNote: hgsvn repository is in an unclean state " "(probably because of an aborted hgpullsvn). \n" "Let's first update to the last good SVN rev."), level=ui.VERBOSE) run_svn(["revert", "-R", "."]) run_svn(["up", "--ignore-externals", "-r", hgsvn_rev, svn_wc]) next_rev = hgsvn_rev + 1 # Reset working branch to last svn head to have a clean and linear SVN # history. heads_before = None if hgsvn_rev is None: heads_before = run_hg(["heads", "--template", "{node}%s" % os.linesep]).splitlines() run_hg(["update", "-C", "svn.%d" % current_rev]) # Load SVN log starting from current rev it_log_entries = iter_svn_log_entries(wc_url, next_rev, svn_greatest_rev, options.svnretry) try: try: for log_entry in it_log_entries: current_rev = pull_svn_rev(log_entry, current_rev, svn_wc, wc_url, wc_base, options.svnretry) if current_rev is None: return 1 ui.status("Pulled r%d %s (%s)", log_entry["revision"], log_entry["message"], log_entry["author"]) # TODO: detect externals with "svn status" and update them as well finally: if heads_before is not None: # we have reset the SVN branch heads_now = run_hg( ["heads", "--template", "{node}%s" % os.linesep]).splitlines() if len(heads_now) != len(heads_before): ui.status("created new head in branch '%s'", svn_branch) work_branch = orig_branch or svn_branch if work_branch != svn_branch: run_hg(["up", '-C', work_branch]) run_hg(["branch", work_branch]) except KeyboardInterrupt: ui.status("\nStopped by user.", level=ui.ERROR) except ExternalCommandFailed, e: ui.status(str(e), level=ui.ERROR)
def real_main(options, args): if run_hg(["st", "-m"]): print( "There are uncommitted changes. Either commit them or put " "them aside before running hgpushsvn.") return 1 if check_for_applied_patches(): print( "There are applied mq patches. Put them aside before " "running hgpushsvn.") return 1 svn_info = get_svn_info(".") svn_current_rev = svn_info["last_changed_rev"] # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted' repos_url = svn_info["repos_url"] # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted/branches/xmpp-subprotocols-2178-2' wc_url = svn_info["url"] assert wc_url.startswith(repos_url) # e.g. u'/branches/xmpp-subprotocols-2178-2' wc_base = wc_url[len(repos_url):] svn_branch = wc_url.split("/")[-1] # Get remote SVN info svn_greatest_rev = get_svn_info(wc_url)['last_changed_rev'] if svn_greatest_rev != svn_current_rev: # We can't go on if the pristine branch isn't up to date. # If the pristine branch lacks some revisions from SVN we are not # able to pull them afterwards. # For example, if the last SVN revision in out hgsvn repository is # r100 and the latest SVN revision is r101, hgpushsvn would create # a tag svn.102 on top of svn.100, but svn.101 isn't in hg history. print("Branch '%s' out of date. Run 'hgpullsvn' first." % svn_branch) return 1 # Switch branches if necessary. orig_branch = run_hg(["branch"]).strip() if orig_branch != svn_branch: if not hg_switch_branch(orig_branch, svn_branch): return 1 hg_start_rev = "svn.%d" % svn_current_rev hg_revs = None try: hg_start_cset = get_hg_cset(hg_start_rev) except RuntimeError: if not options.force: raise hg_start_cset = get_hg_cset("0") print "Warning: revision '%s' not found, forcing to first rev '%s'" % ( hg_start_rev, hg_start_cset) else: if not options.collapse: hg_revs = get_hg_revs(hg_start_cset, svn_branch) if hg_revs is None: hg_revs = [ strip_hg_rev(hg_start_cset), strip_hg_rev(get_hg_cset("tip")) ] pushed_svn_revs = [] try: if options.dryrun: print "Outgoing revisions that would be pushed to SVN:" try: for prev_rev, next_rev in get_pairs(hg_revs): if not options.dryrun: if not options.edit: ui.status("Committing changes up to revision %s", get_hg_cset(next_rev)) username = options.username if options.keep_author: username = run_hg( ["log", "-r", next_rev, "--template", "{author}"]) svn_rev = hg_push_svn(prev_rev, next_rev, edit=options.edit, username=username, password=options.password, cache=options.cache) if svn_rev: # Issue 95 - added update to prevent add/modify/delete crash run_svn(["up"]) map_svn_rev_to_hg(svn_rev, next_rev, local=True) pushed_svn_revs.append(svn_rev) else: print run_hg([ "log", "-r", next_rev, "--template", "{rev}:{node|short} {desc}" ]) except: # TODO: Add --no-backup to leave a "clean" repo behind if something # fails? run_hg(["revert", "--all"]) raise finally: work_branch = orig_branch or svn_branch if work_branch != svn_branch: run_hg(["up", "-C", work_branch]) run_hg(["branch", work_branch]) if pushed_svn_revs: if len(pushed_svn_revs) == 1: msg = "Pushed one revision to SVN: " else: msg = "Pushed %d revisions to SVN: " % len(pushed_svn_revs) run_svn(["up", "-r", pushed_svn_revs[-1]]) ui.status("%s %s", msg, ", ".join(str(x) for x in pushed_svn_revs)) for line in run_hg(["st"]).splitlines(): if line.startswith("M"): ui.status(("Mercurial repository has local changes after " "SVN update.")) ui.status(("This may happen with SVN keyword expansions.")) break elif not options.dryrun: ui.status("Nothing to do.")
def real_main(options, args): if check_for_applied_patches(): print ("There are applied mq patches. Put them aside before " "running hgpullsvn.") return 1 svn_wc = "." # Get SVN info svn_info = get_svn_info('.') current_rev = svn_info['revision'] next_rev = current_rev + 1 # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted' repos_url = svn_info['repos_url'] # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted/branches/xmpp-subprotocols-2178-2' wc_url = svn_info['url'] assert wc_url.startswith(repos_url) # e.g. u'/branches/xmpp-subprotocols-2178-2' wc_base = wc_url[len(repos_url):] # e.g. 'xmpp-subprotocols-2178-2' svn_branch = wc_url.split("/")[-1] # if --branch was passed, override the branch name derived above if options.svn_branch: svn_branch = options.svn_branch if options.svn_peg: wc_url += "@" + str(options.svn_peg) # Get remote SVN info ui.status("Retrieving remote SVN info...", level=ui.VERBOSE) svn_greatest_rev = get_svn_info(wc_url)['last_changed_rev'] if svn_greatest_rev < next_rev: ui.status("No revisions after %s in SVN repo, nothing to do", svn_greatest_rev) return elif options.svn_rev != None: if options.svn_rev < next_rev: ui.status("All revisions up to %s are already pulled in, " "nothing to do", options.svn_rev) return svn_greatest_rev = options.svn_rev # Show incoming changes if in dry-run mode. if options.dryrun: ui.status("Incoming SVN revisions:") for entry in iter_svn_log_entries(wc_url, next_rev, svn_greatest_rev, options.svnretry): if entry["message"]: msg = entry["message"].splitlines()[0].strip() else: msg = "" line = "[%d] %s (%s)" % (entry["revision"], msg, entry["author"]) ui.status(line) return # Prepare and/or switch named branches orig_branch = run_hg(["branch"]).strip() if orig_branch != svn_branch: # Update to or create the "pristine" branch if not hg_switch_branch(orig_branch, svn_branch): return 1 elif not hg_is_clean(svn_branch): return 1 # Detect that a previously aborted hgpullsvn retrieved an SVN revision # without committing it to hg. # If there is no SVN tag in current head, we may have been interrupted # during the previous "hg tag". hgsvn_rev = get_svn_rev_from_hg() if hgsvn_rev is not None and hgsvn_rev != current_rev: ui.status(("\nNote: hgsvn repository is in an unclean state " "(probably because of an aborted hgpullsvn). \n" "Let's first update to the last good SVN rev."), level=ui.VERBOSE) run_svn(["revert", "-R", "."]) run_svn(["up", "--ignore-externals", "-r", hgsvn_rev, svn_wc]) next_rev = hgsvn_rev + 1 # Reset working branch to last svn head to have a clean and linear SVN # history. heads_before = None if hgsvn_rev is None: heads_before = run_hg(["heads", "--template", "{node}%s" % os.linesep]).splitlines() run_hg(["update", "-C", "svn.%d" % current_rev]) # Load SVN log starting from current rev it_log_entries = iter_svn_log_entries(wc_url, next_rev, svn_greatest_rev, options.svnretry) try: try: for log_entry in it_log_entries: current_rev = pull_svn_rev(log_entry, current_rev, svn_wc, wc_url, wc_base, options.svnretry) if current_rev is None: return 1 ui.status("Pulled r%d %s (%s)", log_entry["revision"], log_entry["message"], log_entry["author"]) # TODO: detect externals with "svn status" and update them as well finally: if heads_before is not None: # we have reset the SVN branch heads_now = run_hg(["heads", "--template", "{node}%s" % os.linesep]).splitlines() if len(heads_now) != len(heads_before): ui.status("created new head in branch '%s'", svn_branch) work_branch = orig_branch or svn_branch if work_branch != svn_branch: run_hg(["up", '-C', work_branch]) run_hg(["branch", work_branch]) except KeyboardInterrupt: ui.status("\nStopped by user.", level=ui.ERROR) except ExternalCommandFailed, e: ui.status(str(e), level=ui.ERROR)
def real_main(options, args): if run_hg(["st", "-m"]): print ("There are uncommitted changes. Either commit them or put " "them aside before running hgpushsvn.") return 1 if check_for_applied_patches(): print ("There are applied mq patches. Put them aside before " "running hgpushsvn.") return 1 svn_info = get_svn_info(".") svn_current_rev = svn_info["last_changed_rev"] # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted' repos_url = svn_info["repos_url"] # e.g. u'svn://svn.twistedmatrix.com/svn/Twisted/branches/xmpp-subprotocols-2178-2' wc_url = svn_info["url"] assert wc_url.startswith(repos_url) # e.g. u'/branches/xmpp-subprotocols-2178-2' wc_base = wc_url[len(repos_url):] svn_branch = wc_url.split("/")[-1] # Get remote SVN info svn_greatest_rev = get_svn_info(wc_url)['last_changed_rev'] if svn_greatest_rev != svn_current_rev: # We can't go on if the pristine branch isn't up to date. # If the pristine branch lacks some revisions from SVN we are not # able to pull them afterwards. # For example, if the last SVN revision in out hgsvn repository is # r100 and the latest SVN revision is r101, hgpushsvn would create # a tag svn.102 on top of svn.100, but svn.101 isn't in hg history. print ("Branch '%s' out of date. Run 'hgpullsvn' first." % svn_branch) return 1 # Switch branches if necessary. orig_branch = run_hg(["branch"]).strip() if orig_branch != svn_branch: if not hg_switch_branch(orig_branch, svn_branch): return 1 hg_start_rev = "svn.%d" % svn_current_rev hg_revs = None try: hg_start_cset = get_hg_cset(hg_start_rev) except RuntimeError: if not options.force: raise hg_start_cset = get_hg_cset("0") print "Warning: revision '%s' not found, forcing to first rev '%s'" % ( hg_start_rev, hg_start_cset) else: if not options.collapse: hg_revs = get_hg_revs(hg_start_cset, svn_branch) if hg_revs is None: hg_revs = [strip_hg_rev(hg_start_cset), strip_hg_rev(get_hg_cset("tip"))] pushed_svn_revs = [] try: if options.dryrun: print "Outgoing revisions that would be pushed to SVN:" try: for prev_rev, next_rev in get_pairs(hg_revs): if not options.dryrun: if not options.edit: ui.status("Committing changes up to revision %s", get_hg_cset(next_rev)) username = options.username if options.keep_author: username = run_hg(["log", "-r", next_rev, "--template", "{author}"]) svn_rev = hg_push_svn(prev_rev, next_rev, edit=options.edit, username=username, password=options.password, cache=options.cache) if svn_rev: # Issue 95 - added update to prevent add/modify/delete crash run_svn(["up"]) map_svn_rev_to_hg(svn_rev, next_rev, local=True) pushed_svn_revs.append(svn_rev) else: print run_hg(["log", "-r", next_rev, "--template", "{rev}:{node|short} {desc}"]) except: # TODO: Add --no-backup to leave a "clean" repo behind if something # fails? run_hg(["revert", "--all"]) raise finally: work_branch = orig_branch or svn_branch if work_branch != svn_branch: run_hg(["up", "-C", work_branch]) run_hg(["branch", work_branch]) if pushed_svn_revs: if len(pushed_svn_revs) == 1: msg = "Pushed one revision to SVN: " else: msg = "Pushed %d revisions to SVN: " % len(pushed_svn_revs) run_svn(["up", "-r", pushed_svn_revs[-1]]) ui.status("%s %s", msg, ", ".join(str(x) for x in pushed_svn_revs)) for line in run_hg(["st"]).splitlines(): if line.startswith("M"): ui.status(("Mercurial repository has local changes after " "SVN update.")) ui.status(("This may happen with SVN keyword expansions.")) break elif not options.dryrun: ui.status("Nothing to do.")