Rev 9: Add rebase-todo command, fix rebase-continue. in file:///data/jelmer/bzr-rebase/trunk/
Jelmer Vernooij
jelmer at samba.org
Thu Jul 12 09:22:38 BST 2007
At file:///data/jelmer/bzr-rebase/trunk/
------------------------------------------------------------
revno: 9
revision-id: jelmer at samba.org-20070704211144-x24jnvqimeakxpq0
parent: jelmer at samba.org-20070704203154-3px851kiifoetfry
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: bzr-rebase
timestamp: Wed 2007-07-04 23:11:44 +0200
message:
Add rebase-todo command, fix rebase-continue.
modified:
__init__.py __init__.py-20070626215909-fi0s39bkwxn4gcto-1
rebase.py rebase.py-20070626221123-ellanmf93nw8z9r1-1
test_rebase.py test_rebase.py-20070626221123-ellanmf93nw8z9r1-2
=== modified file '__init__.py'
--- a/__init__.py 2007-07-04 20:31:54 +0000
+++ b/__init__.py 2007-07-04 21:11:44 +0000
@@ -15,7 +15,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from bzrlib.commands import Command, Option, display_command, register_command
-from bzrlib.errors import BzrCommandError, UnrelatedBranches, ConflictsInTree
+from bzrlib.errors import BzrCommandError, UnrelatedBranches, ConflictsInTree, NoSuchFile
+from bzrlib.trace import info
class cmd_rebase(Command):
"""Re-base a branch.
@@ -96,7 +97,10 @@
wt.lock_write()
try:
# Read plan file and set last revision
- last_rev_info = read_rebase_plan(wt)[0]
+ try:
+ last_rev_info = read_rebase_plan(wt)[0]
+ except NoSuchFile:
+ raise BzrCommandError("No rebase to abort")
wt.branch.set_last_revision_info(last_rev_info[0], last_rev_info[1])
wt.set_last_revision(last_rev_info[1])
wt.revert([], backups=False)
@@ -112,7 +116,7 @@
@display_command
def run(self):
- from rebase import read_rebase_plan, rebase_plan_exists, workingtree_replay, rebase, remove_rebase_plan
+ from rebase import read_rebase_plan, rebase_plan_exists, workingtree_replay, rebase, remove_rebase_plan, commit_rebase, read_active_rebase_revid
from bzrlib.workingtree import WorkingTree
wt = WorkingTree.open('.')
wt.lock_write()
@@ -121,8 +125,14 @@
if len(wt.conflicts()) != 0:
raise BzrCommandError("There are still conflicts present")
# Read plan file
- replace_map = read_rebase_plan(wt)[1]
-
+ try:
+ replace_map = read_rebase_plan(wt)[1]
+ except NoSuchFile:
+ raise BzrCommandError("No rebase to continue")
+ oldrevid = read_active_rebase_revid(wt)
+ if oldrevid is not None:
+ oldrev = wt.branch.repository.get_revision(oldrevid)
+ commit_rebase(wt, oldrev, replace_map[oldrevid][0])
try:
# Start executing plan from current Branch.last_revision()
rebase(wt.branch.repository, replace_map, workingtree_replay(wt))
@@ -134,9 +144,33 @@
wt.unlock()
+class cmd_rebase_todo(Command):
+ """Print list of revisions that still need to be replayed as part of the current rebase operation.
+
+ """
+
+ def run(self):
+ from rebase import read_rebase_plan, rebase_todo, read_active_rebase_revid
+ from bzrlib.workingtree import WorkingTree
+ wt = WorkingTree.open('.')
+ wt.lock_read()
+ try:
+ try:
+ replace_map = read_rebase_plan(wt)[1]
+ except NoSuchFile:
+ raise BzrCommandError("No rebase to view")
+ currentrevid = read_active_rebase_revid(wt)
+ if currentrevid is not None:
+ info("Currently replaying: %s" % currentrevid)
+ for revid in rebase_todo(wt.branch.repository, replace_map):
+ info("%s -> %s" % (revid, replace_map[revid][0]))
+ finally:
+ wt.unlock()
+
register_command(cmd_rebase)
register_command(cmd_rebase_abort)
register_command(cmd_rebase_continue)
+register_command(cmd_rebase_todo)
def test_suite():
from unittest import TestSuite
=== modified file 'rebase.py'
--- a/rebase.py 2007-07-04 20:31:54 +0000
+++ b/rebase.py 2007-07-04 21:11:44 +0000
@@ -17,10 +17,12 @@
from bzrlib.config import Config
from bzrlib.errors import UnknownFormatError, NoSuchFile, BzrError
from bzrlib.generate_ids import gen_revision_id
+from bzrlib.revision import NULL_REVISION
from bzrlib.trace import mutter
import bzrlib.ui as ui
REBASE_PLAN_FILENAME = 'rebase-plan'
+REBASE_CURRENT_REVID_FILENAME = 'rebase-current'
REBASE_PLAN_VERSION = 1
def rebase_plan_exists(wt):
@@ -183,6 +185,17 @@
return replace_map
+def rebase_todo(repository, replace_map):
+ """Figure out what revisions still need to be rebased.
+
+ :param repository: Repository that contains the revisions
+ :param replace_map: Replace map
+ """
+ for revid in replace_map:
+ if not repository.has_revision(replace_map[revid][0]):
+ yield revid
+
+
def rebase(repository, replace_map, replay_fn):
"""Rebase a working tree according to the specified map.
@@ -190,10 +203,7 @@
:param replace_map: Dictionary with revisions to (optionally) rewrite
:param merge_fn: Function for replaying a revision
"""
- todo = []
- for revid in replace_map:
- if not repository.has_revision(replace_map[revid][0]):
- todo.append(revid)
+ todo = list(rebase_todo(repository, replace_map))
dependencies = {}
# Figure out the dependencies
@@ -234,7 +244,7 @@
class MapTree:
- def __init__(self, oldtree, old_parents, new_parents):
+ def __init__(self, repository, oldtree, old_parents, new_parents):
self.map = {}
for (oldp, newp) in zip(old_parents, new_parents):
oldinv = repository.get_revision_inventory(oldp)
@@ -252,7 +262,7 @@
def new_id(self, file_id):
try:
- return new_id[file_id]
+ return self.map[file_id]
except KeyError:
return file_id
@@ -292,7 +302,8 @@
# Check what new_ie.file_id should be
# use old and new parent inventories to generate new_id map
- oldtree = MapTree(repository.revision_tree(oldrevid),
+ oldtree = MapTree(repository,
+ repository.revision_tree(oldrevid),
oldrev.parent_ids, new_parents)
oldinv = repository.get_revision_inventory(oldrevid)
total = len(oldinv)
@@ -318,6 +329,20 @@
return builder.commit(oldrev.message)
+def commit_rebase(wt, oldrev, newrevid):
+ """Commit a rebase.
+
+ :param wt: Mutable tree with the changes.
+ :param oldrev: Revision info of new revision to commit.
+ :param newrevid: New revision id."""
+ assert oldrev.revision_id != newrevid
+ revprops = dict(oldrev.properties)
+ revprops['rebase-of'] = oldrev.revision_id
+ wt.commit(message=oldrev.message, timestamp=oldrev.timestamp, timezone=oldrev.timezone,
+ revprops=revprops, rev_id=newrevid)
+ write_active_rebase_revid(wt, None)
+
+
def replay_delta_workingtree(wt, oldrevid, newrevid, newparents, map_ids=False,
merge_type=None):
"""Replay a commit in a working tree, with a different base.
@@ -346,19 +371,15 @@
oldtree = repository.revision_tree(oldrevid)
basetree = repository.revision_tree(oldrev.parent_ids[0])
if map_ids:
- oldtree = MapTree(oldtree, oldrev.parent_ids, new_parents)
- basetree = MapTree(basetree, oldrev.parent_ids, new_parents)
+ oldtree = MapTree(repository, oldtree, oldrev.parent_ids, new_parents)
+ basetree = MapTree(repository, basetree, oldrev.parent_ids, new_parents)
+ write_active_rebase_revid(wt, oldrevid)
merge = merge_type(working_tree=wt, this_tree=wt,
base_tree=basetree,
other_tree=oldtree)
- # commit
- revprops = dict(oldrev.properties)
- revprops['rebase-of'] = oldrevid
- wt.commit(message=oldrev.message, timestamp=oldrev.timestamp, timezone=oldrev.timezone,
- revprops=revprops, rev_id=newrevid)
-
+ commit_rebase(wt, oldrev, newrevid)
def workingtree_replay(wt, map_ids=False):
"""Returns a function that can replay revisions in wt.
@@ -371,5 +392,17 @@
return replay_delta_workingtree(wt, oldrevid, newrevid, newparents)
return replay
-class MergeConflicted(BzrError):
- _fmt = "Conflict during merge"
+
+def write_active_rebase_revid(wt, revid):
+ if revid is None:
+ revid = NULL_REVISION
+ wt._control_files.put_utf8(REBASE_CURRENT_REVID_FILENAME, revid)
+
+def read_active_rebase_revid(wt):
+ try:
+ text = wt._control_files.get(REBASE_CURRENT_REVID_FILENAME).read().rstrip("\n")
+ if text == NULL_REVISION:
+ return None
+ return text
+ except NoSuchFile:
+ return None
=== modified file 'test_rebase.py'
--- a/test_rebase.py 2007-07-04 19:55:29 +0000
+++ b/test_rebase.py 2007-07-04 21:11:44 +0000
@@ -22,7 +22,10 @@
replay_snapshot, generate_simple_plan,
generate_transpose_plan, rebase_plan_exists,
REBASE_PLAN_FILENAME, write_rebase_plan,
- read_rebase_plan, remove_rebase_plan)
+ REBASE_CURRENT_REVID_FILENAME,
+ read_rebase_plan, remove_rebase_plan,
+ read_active_rebase_revid,
+ write_active_rebase_revid)
class RebasePlanReadWriterTests(TestCase):
@@ -205,3 +208,28 @@
self.assertEquals(((1, "bla"), {"oldrev": ("newrev", ["newparent1", "newparent2"])}),
read_rebase_plan(wt))
+class CurrentRevidFileTests(TestCaseWithTransport):
+ def test_read_nonexistant(self):
+ wt = self.make_branch_and_tree('.')
+ self.assertIs(None, read_active_rebase_revid(wt))
+
+ def test_read_null(self):
+ wt = self.make_branch_and_tree('.')
+ wt._control_files.put_utf8(REBASE_CURRENT_REVID_FILENAME, NULL_REVISION)
+ self.assertIs(None, read_active_rebase_revid(wt))
+
+ def test_read(self):
+ wt = self.make_branch_and_tree('.')
+ wt._control_files.put_utf8(REBASE_CURRENT_REVID_FILENAME, "bla")
+ self.assertEquals("bla", read_active_rebase_revid(wt))
+
+ def test_write(self):
+ wt = self.make_branch_and_tree('.')
+ write_active_rebase_revid(wt, "bloe")
+ self.assertEquals("bloe", read_active_rebase_revid(wt))
+
+ def test_write_null(self):
+ wt = self.make_branch_and_tree('.')
+ write_active_rebase_revid(wt, None)
+ self.assertIs(None, read_active_rebase_revid(wt))
+
More information about the bazaar-commits
mailing list