Code review comment for lp:~garyvdm/bzr/bug588698-criss-cross-null-base

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 11/17/2010 7:44 AM, Gary van der Merwe wrote:
> Gary van der Merwe has proposed merging lp:~garyvdm/bzr/bug588698-criss-cross-null-base into lp:bzr.
>
> Requested reviews:
> bzr-core (bzr-core)
> Related bugs:
> #588698 "bzr merge" fails "Branches have no common ancestor"
> https://bugs.launchpad.net/bugs/588698
>
>
> This makes merge choose one of the lcas as the base revision when it cannot locate a unique lca, for example where there is a criss-cross merge of a new root.
>
> It chooses the lca by taking the first lca from find_merge_order(lcas). This seems to give the most sensible for all the user tests I have run.
>
> This has a drive-by fix to make BranchBuilder.build_snapshot accept parent_ids == ['null:']. This was done to make it easier to write a test using BranchBuilder that introduces a new root into the graph.

- - if parent_ids is not None:
+ if parent_ids == [revision.NULL_REVISION]:

^- Are we sure parent_ids is always a list? Could it be a tuple:
(revision.NULL_REVISION,).

I think it usually is. However, you shouldn't need to pass
[NULL_REVISION] either. Just pass the empty list (I think).

+ builder.build_snapshot('B-id', [],
+ [('add', ('', None, 'directory', None))])

I'm not positive if that works, but it does actually match certain bits
of code better. ('null:' isn't saved to the index files, for example).

I'd have to dig a bit deeper to sort out the rest. However, this snippet
looks worrying:

- - self._is_criss_cross = True
+ sorted_lca_keys = self.revision_graph.find_merge_order(

+ revisions[0], lcas)
+ if self.base_rev_id == _mod_revision.NULL_REVISION:
+ self.base_rev_id = sorted_lca_keys[0]
+

graph.find_merge_order is not a cheap operation, because it has to walk
the ancestry. Could we do it only in the 'if' block:

if self.base_rev_id == _mod_revision.NULL_REVISION:
    trace.mutter("hit the NULL_REVISION as the unique LCA."
                 " Picking the 'first' lca as BASE")
    sorted_lca_keys = self.revision_graph.find_merge_order(revisions[0],
lcas)
    self.base_rev_id = sorted_lca_keys[0]

...

                 interesting_revision_ids = [self.base_rev_id]
                 interesting_revision_ids.extend(lcas)
+ interesting_revision_ids =
list(set(interesting_revision_ids))

^- This doesn't preserve the ordering of interesting_revision_ids. But
since it looks like we don't need the specific order, why not just use a
set and not cast to a list in the first place?

I see that 'sorted_lca_keys' is used again right after this point. but
is it used in all possible cases?

Anyway, the basic concept seems fine. Failing down to NULL_REVISION is
bad, picking a 'best guess' LCA seems reasonable. We may want to inform
the user that we did this, in case it would be confusing why X or Y
didn't happen. At least a mutter() helps us debug it if it is happening.

John
=:->

 review: needs_information
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkzkQ4IACgkQJdeBCYSNAAMgYgCguFfjAzaaqfSrF6Gk6PXUXLhk
2SUAmwX6f8VIy3ysiGDNTpbWf6XCvq3X
=Dw1c
-----END PGP SIGNATURE-----

review: Needs Information

« Back to merge proposal