[MERGE] pull converges

Martin Pool mbp at sourcefrog.net
Wed Apr 12 05:58:17 BST 2006


On 12/04/2006, at 2:13 PM, Robert Collins wrote:

> This is an updated patch, it adds the requested doco - does that look
> ok ? and also adds a test for pulling when a merge was indirectly done
> to the parent.

> === modified file 'a/NEWS'
> --- a/NEWS	
> +++ b/NEWS	
> @@ -66,6 +66,10 @@
>      * New 'init-repository' command, plus support for repositories  
> in 'init'
>        and 'branch' (Aaron Bentley, Erik Bågfors)
> +
> +    * 'pull' and 'push' now normalise the revision history, so  
> that any two
> +      branches with the same tip revision will have the same  
> output from 'log'.
> +      (Robert Collins)
>    CHANGES:

This is not quite precisely what the patch does -- after pulling in  
one direction the two branches are not guaranteed to be the same if  
the source was not canonical.  Perhaps this is too subtle to explain  
in the news file.

> +    @needs_write_lock
>      def update_revisions(self, other, stop_revision=None):
>          """See Branch.update_revisions."""
> -        if stop_revision is None:
> -            stop_revision = other.last_revision()
> -        ### Should this be checking is_ancestor instead of  
> revision_history?
> -        if (stop_revision is not None and
> -            stop_revision in self.revision_history()):
> -            return
> -        self.fetch(other, stop_revision)
> -        pullable_revs = self.pullable_revisions(other, stop_revision)
> -        if len(pullable_revs) > 0:
> -            self.append_revision(*pullable_revs)
> -
> +        other.lock_read()
> +        try:
> +            if stop_revision is None:
> +                stop_revision = other.last_revision()
> +                if stop_revision is None:
> +                    # if there are no commits, we're done.
> +                    return
> +            # whats the current last revision, before we fetch  
> [and change it
> +            # possibly]
> +            last_rev = self.last_revision()
> +            # we fetch here regardless of whether we need to so  
> that we pickup
> +            # filled in ghosts.
> +            self.fetch(other, stop_revision)
> +            my_ancestry = self.repository.get_ancestry(last_rev)
> +            if stop_revision in my_ancestry:
> +                # last_revision is a descendant of stop_revision
> +                return
> +            # stop_revision must be a descendant of last_revision
> +            stop_graph = self.repository.get_revision_graph 
> (stop_revision)
> +            if last_rev is not None and last_rev not in stop_graph:
> +                # our previous tip is not merged into stop_revision
> +                raise errors.DivergedBranches(self, other)
> +            # make a new revision history from the graph
> +            current_rev_id = stop_revision
> +            new_history = []
> +            while current_rev_id not in (None, NULL_REVISION):
> +                new_history.append(current_rev_id)
> +                current_rev_id_parents = stop_graph[current_rev_id]
> +                try:
> +                    current_rev_id = current_rev_id_parents[0]
> +                except IndexError:
> +                    current_rev_id = None
> +            new_history.reverse()
> +            self.set_revision_history(new_history)
> +        finally:
> +            other.unlock()
> +

it would be nice if this method was smaller.

+1

-- 
Martin







More information about the bazaar mailing list