Merge lp:~luoyonggang/bzr-svn/perfect-layout into lp:bzr-svn/1.1

Proposed by Yonggang Luo
Status: Rejected
Rejected by: Jelmer Vernooij
Proposed branch: lp:~luoyonggang/bzr-svn/perfect-layout
Merge into: lp:bzr-svn/1.1
Diff against target: 503 lines (+371/-35)
5 files modified
commands.py (+11/-29)
layout/__init__.py (+3/-0)
layout/perfect.py (+345/-0)
layout/standard.py (+1/-1)
repository.py (+11/-5)
To merge this branch: bzr merge lp:~luoyonggang/bzr-svn/perfect-layout
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) Disapprove
Review via email: mp+64530@code.launchpad.net

Description of the change

There is indent fixup.

Mainly focused on get perfect working with bzr-svn's layout!

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Hi,

On 14/06/11 12:57, Yonggang Luo wrote:
> Yonggang Luo has proposed merging lp:~luoyonggang/bzr-svn/perfect-layout into lp:bzr-svn.
>
> Requested reviews:
> Jelmer Vernooij (jelmer)
>
> For more details, see:
> https://code.launchpad.net/~luoyonggang/bzr-svn/perfect-layout/+merge/64530
>
> There is indent fixup.
>
> Mainly focused on get perfect working with bzr-svn's layout!
In general, please submit merge proposals for specific changes. That
makes it possible to merge those specific changes without having to
reject the entire MP (like this one).

You seem to be deleting a few things that are there for good reasons.
Please keep the following around:

* The --layout option in svn-import - removing it breaks existing users
who rely on it, or might have scripts that rely on it
* Guessing of layouts in "bzr svn-import". It's there for a reason - to
prevent users from shooting themselves in the foot.

I don't see why prefix isn't relevant for PerfectLayout; shouldn't users
be able to fetch just a part of the repository?

Please don't call your custom layout "perfect". It may be perfect for
you, it's not a good fit for everybody and that name doesn't really
explain how it works. What about "copytracking" ?

As we discussed earlier, please don't register your layout in the layout
registry as it needs to have the LogWalker passed in. Instead, please
add a configuration option for it, look for that option in
Repository.get_layout() and return PerfectLayout(self._log) from there.

Cheers,

Jelmer

Revision history for this message
Jelmer Vernooij (jelmer) :
review: Disapprove
Revision history for this message
Yonggang Luo (luoyonggang) wrote :

2011/6/14 Jelmer Vernooij <email address hidden>

> Hi,
>
> On 14/06/11 12:57, Yonggang Luo wrote:
> > Yonggang Luo has proposed merging lp:~luoyonggang/bzr-svn/perfect-layout
> into lp:bzr-svn.
> >
> > Requested reviews:
> > Jelmer Vernooij (jelmer)
> >
> > For more details, see:
> >
> https://code.launchpad.net/~luoyonggang/bzr-svn/perfect-layout/+merge/64530
> >
> > There is indent fixup.
> >
> > Mainly focused on get perfect working with bzr-svn's layout!
> In general, please submit merge proposals for specific changes. That
> makes it possible to merge those specific changes without having to
> reject the entire MP (like this one).
>
I don't know how to do that.

>
> You seem to be deleting a few things that are there for good reasons.
> Please keep the following around:
>
> * The --layout option in svn-import - removing it breaks existing users
> who rely on it, or might have scripts that rely on it
> * Guessing of layouts in "bzr svn-import". It's there for a reason - to
> prevent users from shooting themselves in the foot.
>
Did not affecting of bzr svn-import . I've tested.
Why I ignore prefix? I am not ignore of it, just because of PerfectLayout
need using of it
PerfectLayout need manage of prefix by its self.

>
> I don't see why prefix isn't relevant for PerfectLayout; shouldn't users
> be able to fetch just a part of the repository?
>
> Please don't call your custom layout "perfect". It may be perfect for
> you, it's not a good fit for everybody and that name doesn't really
> explain how it works. What about "copytracking" ?
>
Err.. you should tell me earlier, such as the last discussion!

> As we discussed earlier, please don't register your layout in the layout
>
NO。。。it's not working, when I was trying, all kinds of problem is appeared..

> registry as it needs to have the LogWalker passed in. Instead, please
> add a configuration option for it, look for that option in
> Repository.get_layout() and return PerfectLayout(self._log) from there.
>
> Cheers,
>
> Jelmer
>
> --
> https://code.launchpad.net/~luoyonggang/bzr-svn/perfect-layout/+merge/64530
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>

--
         此致

罗勇刚
Yours
    sincerely,
Yonggang Luo

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 14/06/11 13:43, Yonggang Luo wrote:
> 2011/6/14 Jelmer Vernooij <email address hidden>
>
>
>> In general, please submit merge proposals for specific changes. That
>> makes it possible to merge those specific changes without having to
>> reject the entire MP (like this one).
>>
> I don't know how to do that.
I mean create different branches and propose them for merging against
lp:bzr separately.
>> You seem to be deleting a few things that are there for good reasons.
>> Please keep the following around:
>>
>> * The --layout option in svn-import - removing it breaks existing users
>> who rely on it, or might have scripts that rely on it
>> * Guessing of layouts in "bzr svn-import". It's there for a reason - to
>> prevent users from shooting themselves in the foot.
>>
> Did not affecting of bzr svn-import . I've tested.
> Why I ignore prefix? I am not ignore of it, just because of PerfectLayout
> need using of it
> PerfectLayout need manage of prefix by its self.
prefix is used to restrict which paths are imported. If I specify:

bzr svn-import svn://svn.llvm.org/llvm-gcc and svn://svn.llvm.org/ is
the repository root I expect only the llvm-gcc part of the repository to
be imported, and not any of the other projects. Ignoring prefix means
all projects in the repository will be imported.

>> I don't see why prefix isn't relevant for PerfectLayout; shouldn't users
>> be able to fetch just a part of the repository?
>>
>> Please don't call your custom layout "perfect". It may be perfect for
>> you, it's not a good fit for everybody and that name doesn't really
>> explain how it works. What about "copytracking" ?
>>
> Err.. you should tell me earlier, such as the last discussion!
? We never discussed the name of your layout before as far as I
remember, and we never looked at any code.

>> As we discussed earlier, please don't register your layout in the layout
>>
> NO。。。it's not working, when I was trying, all kinds of problem is appeared..
Can you be more specific, what exactly didn't work?

Cheers,

Jelmer

Revision history for this message
Yonggang Luo (luoyonggang) wrote :

2011/6/14 Jelmer Vernooij <email address hidden>

> On 14/06/11 13:43, Yonggang Luo wrote:
> > 2011/6/14 Jelmer Vernooij <email address hidden>
> >
> >
> >> In general, please submit merge proposals for specific changes. That
> >> makes it possible to merge those specific changes without having to
> >> reject the entire MP (like this one).
> >>
> > I don't know how to do that.
> I mean create different branches and propose them for merging against
> lp:bzr separately.
>

That's too much complicated. It's just leading the development progress too
depression.
Is there any other way?

>> You seem to be deleting a few things that are there for good reasons.
> >> Please keep the following around:
> >>
> >> * The --layout option in svn-import - removing it breaks existing users
> >> who rely on it, or might have scripts that rely on it
> >> * Guessing of layouts in "bzr svn-import". It's there for a reason - to
> >> prevent users from shooting themselves in the foot.
> >>
> > Did not affecting of bzr svn-import . I've tested.
> > Why I ignore prefix? I am not ignore of it, just because of PerfectLayout
> > need using of it
> > PerfectLayout need manage of prefix by its self.
> prefix is used to restrict which paths are imported. If I specify:
>
> bzr svn-import svn://svn.llvm.org/llvm-gcc and svn://svn.llvm.org/ is
> the repository root I expect only the llvm-gcc part of the repository to
> be imported, and not any of the other projects. Ignoring prefix means
> all projects in the repository will be imported.
>
>
> >> I don't see why prefix isn't relevant for PerfectLayout; shouldn't users
> >> be able to fetch just a part of the repository?
> >>
> >> Please don't call your custom layout "perfect". It may be perfect for
> >> you, it's not a good fit for everybody and that name doesn't really
> >> explain how it works. What about "copytracking" ?
> >>
> > Err.. you should tell me earlier, such as the last discussion!
> ? We never discussed the name of your layout before as far as I
> remember, and we never looked at any code.
>
> You mentioned PerfectLayout at freenode, so I was think you were accepted
of it.

> >> As we discussed earlier, please don't register your layout in the
> layout
> >>
> > NO。。。it's not working, when I was trying, all kinds of problem is
> appeared..
> Can you be more specific, what exactly didn't work?
>
> The code in commands.py that I removed.

> Cheers,
>
> Jelmer
>
> --
> https://code.launchpad.net/~luoyonggang/bzr-svn/perfect-layout/+merge/64530
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>

--
         此致

罗勇刚
Yours
    sincerely,
Yonggang Luo

3734. By Yonggang Luo

Add it first!

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 14/06/11 14:07, Yonggang Luo wrote:
> 2011/6/14 Jelmer Vernooij <email address hidden>
>
>> On 14/06/11 13:43, Yonggang Luo wrote:
>>> 2011/6/14 Jelmer Vernooij <email address hidden>
>>>
>>>
>>>> In general, please submit merge proposals for specific changes. That
>>>> makes it possible to merge those specific changes without having to
>>>> reject the entire MP (like this one).
>>>>
>>> I don't know how to do that.
>> I mean create different branches and propose them for merging against
>> lp:bzr separately.
>>
> That's too much complicated. It's just leading the development progress too
> depression.
> Is there any other way?
It's fine with me if you want to submit bigger branches, I was just
suggesting smaller branches since they can be landed independently.
>>>> I don't see why prefix isn't relevant for PerfectLayout; shouldn't users
>>>> be able to fetch just a part of the repository?
>>>>
>>>> Please don't call your custom layout "perfect". It may be perfect for
>>>> you, it's not a good fit for everybody and that name doesn't really
>>>> explain how it works. What about "copytracking" ?
>>>>
>>> Err.. you should tell me earlier, such as the last discussion!
>> ? We never discussed the name of your layout before as far as I
>> remember, and we never looked at any code.

> You mentioned PerfectLayout at freenode, so I was think you were accepted
> of it.
I mean we didn't explicitly discuss the name - I don't like it for the
reasons specified earlier.

Cheers,

Jelmer

Revision history for this message
Yonggang Luo (luoyonggang) wrote :

Another problem, because of repo already have an function named with
get_layout
Why another get_layout resident at command.py?

I think they must be at the same place. It's easier to management.

--
         此致

罗勇刚
Yours
    sincerely,
Yonggang Luo

Revision history for this message
Yonggang Luo (luoyonggang) wrote :

Why this error arising, it's looks weird.. I have no idea on this, on
another computer, it's works fine.
ssh -v luoyonggang@<email address hidden>
OpenSSH_5.8p1, OpenSSL 0.9.8r 8 Feb 2011
debug1: Reading configuration data /cygdrive/d/CI/docs/home/lyg/.ssh/config
debug1: Applying options for bazaar.launchpad.net
debug1: Connecting to bazaar.launchpad.net [91.189.90.11] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /cygdrive/d/CI/docs/home/lyg/.ssh/id_rsa type 1
debug1: identity file /cygdrive/d/CI/docs/home/lyg/.ssh/id_rsa-cert type -1
debug1: Remote protocol version 2.0, remote software version Twisted
debug1: no match: Twisted
debug1: Enabling compatibility mode for protocol 2.0
      4 [main] ssh 5584 exception::handle: Exception:
STATUS_ACCESS_VIOLATION
   3075 [main] ssh 5584 open_stackdumpfile: Dumping stack trace to
ssh.exe.stack
dump

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 14/06/11 15:58, Yonggang Luo wrote:
> Another problem, because of repo already have an function named with
> get_layout
> Why another get_layout resident at command.py?
I don't think that's a problem, they have a different scope. get_layout
in commands.py could be renamed to get_layout_by_name or something like
that, but I don't see any reason to do so.
>
> I think they must be at the same place. It's easier to management.
They do different things; one is a UI layer helper for getting a layout by name. The other is for finding the layout to use for a repository.

Cheers,

Jelmer

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 14/06/11 15:59, Yonggang Luo wrote:
> Why this error arising, it's looks weird.. I have no idea on this, on
> another computer, it's works fine.
> ssh -v luoyonggang@<email address hidden>
> OpenSSH_5.8p1, OpenSSL 0.9.8r 8 Feb 2011
> debug1: Reading configuration data /cygdrive/d/CI/docs/home/lyg/.ssh/config
> debug1: Applying options for bazaar.launchpad.net
> debug1: Connecting to bazaar.launchpad.net [91.189.90.11] port 22.
> debug1: Connection established.
> debug1: permanently_set_uid: 0/0
> debug1: identity file /cygdrive/d/CI/docs/home/lyg/.ssh/id_rsa type 1
> debug1: identity file /cygdrive/d/CI/docs/home/lyg/.ssh/id_rsa-cert type -1
> debug1: Remote protocol version 2.0, remote software version Twisted
> debug1: no match: Twisted
> debug1: Enabling compatibility mode for protocol 2.0
> 4 [main] ssh 5584 exception::handle: Exception:
> STATUS_ACCESS_VIOLATION
> 3075 [main] ssh 5584 open_stackdumpfile: Dumping stack trace to
> ssh.exe.stack
> dump
Looks like a segfaulting ssh client; the cygwin bug tracker is probably
a more appropriate place for that.

Cheers,

jelmer

Revision history for this message
Yonggang Luo (luoyonggang) wrote :

>
>
> > debug1: Enabling compatibility mode for protocol 2.0
> > 4 [main] ssh 5584 exception::handle: Exception:
> > STATUS_ACCESS_VIOLATION
> > 3075 [main] ssh 5584 open_stackdumpfile: Dumping stack trace to
> > ssh.exe.stack
> > dump
> Looks like a segfaulting ssh client; the cygwin bug tracker is probably
> a more appropriate place for that.
>
> Thanks, by using of putty, its working, ssh.exe still not working, I found
that problem appeared before under cygwin mailling list. but they didn't
resolved at last:)

--
         此致

罗勇刚
Yours
    sincerely,
Yonggang Luo

Revision history for this message
Yonggang Luo (luoyonggang) wrote :

2011/6/14 Jelmer Vernooij <email address hidden>

> On 14/06/11 15:58, Yonggang Luo wrote:
> > Another problem, because of repo already have an function named with
> > get_layout
> > Why another get_layout resident at command.py?
> I don't think that's a problem, they have a different scope. get_layout
> in commands.py could be renamed to get_layout_by_name or something like
> that, but I don't see any reason to do so.
> >
> > I think they must be at the same place. It's easier to management.
> They do different things; one is a UI layer helper for getting a layout by
> name. The other is for finding the layout to use for a repository.
>
> I know they were different things, I means the UI only provide the
layoutname, and the creating of Layout will at the single point. so we can
separate it up. Right place do the right things, UI's main function is
providing the parameters, and these parameters are used by repository:)

> Cheers,
>
> Jelmer
>
>
> --
> https://code.launchpad.net/~luoyonggang/bzr-svn/perfect-layout/+merge/64530
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>

--
         此致

罗勇刚
Yours
    sincerely,
Yonggang Luo

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 14/06/11 16:36, Yonggang Luo wrote:
> 2011/6/14 Jelmer Vernooij <email address hidden>
>
>> On 14/06/11 15:58, Yonggang Luo wrote:
>>> Another problem, because of repo already have an function named with
>>> get_layout
>>> Why another get_layout resident at command.py?
>> I don't think that's a problem, they have a different scope. get_layout
>> in commands.py could be renamed to get_layout_by_name or something like
>> that, but I don't see any reason to do so.
>>> I think they must be at the same place. It's easier to management.
>> They do different things; one is a UI layer helper for getting a layout by
>> name. The other is for finding the layout to use for a repository.

> I know they were different things, I means the UI only provide the
> layoutname, and the creating of Layout will at the single point. so we can
> separate it up. Right place do the right things, UI's main function is
> providing the parameters, and these parameters are used by repository:)
That's already the case - the actual looking up is happening with this
single line of code in both cases:

ret = layout_registry.get(layoutname)()

The UI helper function has some logic to cope with the fact that command
line options can be unicode (whereas layout names are strictly ascii at
the moment), and it has some code to display a command line user error
if the specific layout was not found.

Cheers,

Jelmer

Revision history for this message
Yonggang Luo (luoyonggang) wrote :

2011/6/14 Jelmer Vernooij <email address hidden>

> On 14/06/11 16:36, Yonggang Luo wrote:
> > 2011/6/14 Jelmer Vernooij <email address hidden>
> >
> >> On 14/06/11 15:58, Yonggang Luo wrote:
> >>> Another problem, because of repo already have an function named with
> >>> get_layout
> >>> Why another get_layout resident at command.py?
> >> I don't think that's a problem, they have a different scope. get_layout
> >> in commands.py could be renamed to get_layout_by_name or something like
> >> that, but I don't see any reason to do so.
> >>> I think they must be at the same place. It's easier to management.
> >> They do different things; one is a UI layer helper for getting a layout
> by
> >> name. The other is for finding the layout to use for a repository.
>
> > I know they were different things, I means the UI only provide the
> > layoutname, and the creating of Layout will at the single point. so we
> can
> > separate it up. Right place do the right things, UI's main function is
> > providing the parameters, and these parameters are used by repository:)
> That's already the case - the actual looking up is happening with this
> single line of code in both cases:
>
> ret = layout_registry.get(layoutname)()
>
> That's why I mentioned to merge this two function, it's implement the same
function at two different place and get the things
to be complicated? Don't you realized of this?

Compare the codebase bzr-svn with hgsubversion, one is 600kb+, one is 150kb,
I don't think bzr-svn implement much more function than hgsubversion, but
why the codebase is so large? Even though the framework is better, but the
codebase is really redundant, this is one of the example, I was try to let
you realize of it, but you just ignore of that.
Python is a script language, but you using it like a c language. That's I
want to say.

Sorry for the critical, but that's an fact.

> The UI helper function has some logic to cope with the fact that command
> line options can be unicode (whereas layout names are strictly ascii at
> the moment), and it has some code to display a command line user error
> if the specific layout was not found.
>
> That's what I was accepted, but I think should implement an function
get_layoutname, but not get_layout, because get_layout is the working of
repository... Do don't implement the same function here and there. that's
make no sense.

> Cheers,
>
> Jelmer
>
>
>
> --
> https://code.launchpad.net/~luoyonggang/bzr-svn/perfect-layout/+merge/64530
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>

--
         此致

罗勇刚
Yours
    sincerely,
Yonggang Luo

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On 14/06/11 17:31, Yonggang Luo wrote:
> 2011/6/14 Jelmer Vernooij <email address hidden>
>
>> On 14/06/11 16:36, Yonggang Luo wrote:
>>> 2011/6/14 Jelmer Vernooij <email address hidden>
>>>
>>>> On 14/06/11 15:58, Yonggang Luo wrote:
>>>>> Another problem, because of repo already have an function named with
>>>>> get_layout
>>>>> Why another get_layout resident at command.py?
>>>> I don't think that's a problem, they have a different scope. get_layout
>>>> in commands.py could be renamed to get_layout_by_name or something like
>>>> that, but I don't see any reason to do so.
>>>>> I think they must be at the same place. It's easier to management.
>>>> They do different things; one is a UI layer helper for getting a layout
>> by
>>>> name. The other is for finding the layout to use for a repository.
>>> I know they were different things, I means the UI only provide the
>>> layoutname, and the creating of Layout will at the single point. so we
>> can
>>> separate it up. Right place do the right things, UI's main function is
>>> providing the parameters, and these parameters are used by repository:)
>> That's already the case - the actual looking up is happening with this
>> single line of code in both cases:
>>
>> ret = layout_registry.get(layoutname)()
>>

> That's why I mentioned to merge this two function, it's implement the same
> function at two different place and get the things
> to be complicated? Don't you realized of this?
These two functions do really different things. One could be called
get_layout_for_repository and the other could be called
get_layout_by_name. If you think they can be merged, I'm happy to review
a merge proposal to that extend, but they only really have one line in
common (the one I mentioned earlier). I'm not sure how that could be
factored out.

>
> Compare the codebase bzr-svn with hgsubversion, one is 600kb+, one is 150kb,
> I don't think bzr-svn implement much more function than hgsubversion, but
> why the codebase is so large? Even though the framework is better, but the
> codebase is really redundant, this is one of the example, I was try to let
> you realize of it, but you just ignore of that.
> Python is a script language, but you using it like a c language. That's I
> want to say.
Unlike hgsubversion, bzr-svn allows random access to svn repositories,
it doesn't just allow pushing and pulling. It also supports
roundtripping push (push that preserves all metadata). I'm not sure if
that qualifies the larger size of the project, but that's definitely one
of the reasons.

I'm happy to merge branches that remove redundancy where it is present.
However, so far you haven't mentioned anything that would actually
simplify the code base *without* throwing away existing features.

How is the codebase C like?

Cheers,

jelmer

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Marking as rejected for the moment, please change back to "needs review" when applicable.

Unmerged revisions

3734. By Yonggang Luo

Add it first!

3733. By Yonggang Luo

No prefix for perfect.
We need all history:!

3732. By Yonggang Luo

Create layout on an single place!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'commands.py'
2--- commands.py 2010-12-26 14:29:55 +0000
3+++ commands.py 2011-06-14 12:09:26 +0000
4@@ -30,21 +30,14 @@
5 )
6
7
8-def get_layout(layoutname):
9- """Parse layout name and return a layout.
10+def get_layoutname(layoutname):
11+ """Parse layout name and return a normal layout name.
12
13 :param layout: Name of the layout to retrieve.
14 """
15 if isinstance(layoutname, unicode):
16 layoutname = layoutname.encode("ascii")
17- from bzrlib.plugins.svn.layout import layout_registry
18- from bzrlib.errors import BzrCommandError
19-
20- try:
21- ret = layout_registry.get(layoutname)()
22- except KeyError:
23- raise BzrCommandError('No such repository layout %r' % layoutname)
24- return ret
25+ return layoutname
26
27
28 class cmd_svn_import(Command):
29@@ -70,7 +63,7 @@
30 Option('all',
31 help='Convert all revisions, even those not in '
32 'current branch history.'),
33- Option('layout', type=get_layout,
34+ Option('layoutname', type=get_layoutname,
35 help='Repository layout (none, trunk, etc). '
36 'Default: auto.'),
37 Option('keep',
38@@ -87,7 +80,7 @@
39 ]
40
41 def run(self, from_location, to_location=None, format=None, trees=False,
42- standalone=False, layout=None, all=False, prefix=None, keep=False,
43+ standalone=False, layoutname=None, all=False, prefix=None, keep=False,
44 restore=False, until=None):
45 from bzrlib import (
46 osutils,
47@@ -152,25 +145,12 @@
48 from_repos.lock_read()
49 try:
50 if prefix is not None:
51- if layout is None:
52- overall_layout = from_repos.get_guessed_layout()
53- else:
54- overall_layout = layout
55 prefix = prefix.strip("/") + "/"
56- if overall_layout.is_branch(prefix):
57- raise BzrCommandError("%s appears to contain a branch. "
58- "For individual branches, use 'bzr branch'." %
59- from_location)
60- # FIXME: Hint about is_tag()
61- elif overall_layout.is_branch_parent(prefix):
62- self.outf.write("Importing branches with prefix /%s\n" %
63- urlutils.unescape_for_display(prefix, self.outf.encoding))
64- else:
65- raise BzrCommandError("The specified path is inside a branch. "
66- "Specify a different URL or a different repository layout (see also 'bzr help svn-layout').")
67
68 if (prefix is not None and
69 from_repos.transport.check_path(prefix, to_revnum) == NODE_NONE):
70+ #TODO:Is this really necessary? because once a branch removed in SVN.
71+ #Then SVN won't see it anymore, but it's sill in the history!
72 raise BzrCommandError("Prefix %s does not exist" % prefix)
73
74 def filter_branch(branch):
75@@ -179,8 +159,10 @@
76 return False
77 return True
78
79- trace.note("Using repository layout: %s",
80- layout or from_repos.get_layout())
81+ layout = from_repos.get_layout(layoutname, prefix)
82+ if layoutname is 'perfect':
83+ prefix = None
84+ trace.note("Using repository layout: %s", layout)
85 convert_repository(from_repos, to_location, layout,
86 not standalone, trees, all, format=format,
87 filter_branch=filter_branch, keep=keep,
88
89=== modified file 'layout/__init__.py'
90--- layout/__init__.py 2011-06-07 00:39:20 +0000
91+++ layout/__init__.py 2011-06-14 12:09:26 +0000
92@@ -306,6 +306,9 @@
93 layout_registry.register_lazy("itrunk3", "bzrlib.plugins.svn.layout.standard",
94 "InverseTrunkLayout3")
95
96+layout_registry.register_lazy("perfect", "bzrlib.plugins.svn.layout.perfect",
97+ "PerfectLayout")
98+
99 class RepositoryRegistry(registry.Registry):
100
101 def get(self, name):
102
103=== added file 'layout/perfect.py'
104--- layout/perfect.py 1970-01-01 00:00:00 +0000
105+++ layout/perfect.py 2011-06-14 12:09:26 +0000
106@@ -0,0 +1,345 @@
107+from subvertpy import NODE_DIR
108+
109+from bzrlib import urlutils
110+from bzrlib.plugins.svn import errors as svn_errors
111+from bzrlib.plugins.svn.layout import (
112+ RepositoryLayout,
113+ get_root_paths,
114+ wildcard_matches,
115+ )
116+
117+class SVNBranches(object):
118+ def __init__(self, _subdir):
119+
120+
121+ def localname_tag(self, path):
122+ if self.meta.layout == 'single':
123+ return 'tip'
124+ default_tag_prefix = self.subdir + 'tags/'
125+ if path == self.subdir + 'trunk' or path is None:
126+ return 'tip'
127+ elif path.startswith(default_tag_prefix):
128+ return path[len(default_tag_prefix):]
129+ return path
130+
131+ def remotename_tag(self, tag):
132+ if self.meta.layout == 'single':
133+ return '/'
134+ if tag == 'tip' or tag is None:
135+ return self.subdir + 'trunk'
136+ elif tag.startswith('/'):
137+ return tag
138+ return self.subdir + 'tags/' + tag
139+
140+ def get_tag_name(self, branch_info = None):
141+ if self.meta.layout == 'single':
142+ return None
143+ if not branch_info:
144+ return None
145+ if not self.exist_branch(branch_info[2], branch_info[3]):
146+ return None
147+ return self.is_tag(branch_info[0])
148+
149+ def is_tag(self, branch_path):
150+ for tagspath in self.tag_locations:
151+ tag_prefix = self.subdir + tagspath + '/'
152+ if branch_path.startswith(tag_prefix):
153+ return self.localname_tag(branch_path)
154+ return None
155+
156+ def get_paths(self, revision):
157+ paths = {}
158+ for p,item in revision.paths.iteritems():
159+ paths[p] = svn_changes(item)
160+ return paths
161+
162+ def update(self, svn, revision):
163+ """
164+ Given a revision object, determine changes to branches.
165+ """
166+ self.added_tags, self.deleted_tags = {},{}
167+ self.deleted_branches = set()
168+ self.modified = {}
169+ if self.meta.layout == 'single':
170+ self.modified['/'] = 1
171+ self.all_branches = {'/':{-1:['/', 0, 1]}}
172+ return
173+
174+ paths, revnum = self.get_paths(revision), revision.revnum
175+ print(paths, revnum)
176+ sorted_paths = sorted(paths.keys())
177+ current_test_branches = frozenset(self.all_branches.keys())
178+ for p in sorted_paths:
179+ if paths[p].action != 'D' and paths[p].action != 'R':
180+ continue
181+ np = p + '/'
182+ for branch_path in current_test_branches:
183+ if not self.exist_branch(branch_path, revnum):
184+ continue
185+ if not (branch_path + '/').startswith(np):
186+ continue
187+ self.remove_branch(branch_path, revnum)
188+
189+ for p in sorted_paths:
190+ copy_from_path = paths[p].copyfrom_path
191+ if (copy_from_path is None):
192+ continue
193+ copy_from_path += '/'
194+ parent_rev = paths[p].copyfrom_rev
195+ for parent_path in current_test_branches:
196+ rn = parent_path + '/'
197+ if not rn.startswith(copy_from_path):
198+ continue
199+ if not self.exist_branch(parent_path, parent_rev):
200+ continue
201+ suffix = ''
202+ if (rn != copy_from_path):
203+ suffix = parent_path[len(copy_from_path) - 1:]
204+ new_branch_path = p + suffix
205+ if self.real_branch(new_branch_path) == new_branch_path:
206+ self.add_branch(new_branch_path, revnum, parent_path, parent_rev)
207+
208+ for p in sorted_paths:
209+ new_branch_path = None
210+ branch_info = self.get_file_branch(p, revnum)[1]
211+ if branch_info is None:
212+ new_branch_path = self.create_branch(p)
213+ else:
214+ self.modified[branch_info[0]] = 1
215+ if (paths[p].action == 'D'):
216+ continue
217+ if self.contains_branch(p, revnum):
218+ continue
219+
220+ # If p is an exist file at in some current opened branch
221+
222+ #Now, /llvm/branches/Apple/williamson processed at the begining!
223+ #Carefully handle there is copyfrom, but the from palce didn't have any branches!
224+ cp_from = paths[p].copyfrom_path
225+ if ( (cp_from and not cp_from.startswith(self.subdir)
226+ and self.real_branch(p) == p
227+ and (branch_info == None or branch_info[3] == 0)) #This means copies outside the current subdir
228+ or self.exist_branch(p, revnum, 2) != None): #This means there is an branch at path p before:)
229+ new_branch_path = p
230+
231+ if new_branch_path and svn.checkpath(p.lstrip('/'), revnum) == 'd':
232+ sub_path = self.get_file_path(p, new_branch_path)
233+ parent_path, parent_rev = self.subdir + 'trunk', 0
234+ if cp_from:
235+ parent_path = cp_from[:len(cp_from) - len(sub_path)]
236+ parent_rev = paths[p].copyfrom_rev
237+ if sub_path != '':
238+ self.modified[new_branch_path] = 1
239+ print("Try add branch with ",p , str(new_branch_path) +':' + str(revnum), sub_path, parent_path + ':' + str(parent_rev))
240+ self.add_branch(new_branch_path, revnum, parent_path, parent_rev)
241+
242+ def contains_branch(self, path, revnum):
243+ for branch_path, revlist in self.all_branches.iteritems():
244+ if not branch_path.startswith(path):
245+ continue
246+ if -1 in revlist:
247+ return True
248+ return False
249+
250+ def real_branch(self, path, ret_original = True):
251+ new_path = path + '/'
252+ #TODO: We can fitler more, user can specify which folder can't
253+ #contains newly created branch:)
254+ trunk_suffix = '/trunk/'
255+ index = new_path.find("/trunk/")
256+ if index == -1:
257+ if ret_original:
258+ return path
259+ return None
260+ index = index + len(trunk_suffix)
261+ path = new_path[0:index - 1]
262+ return path
263+
264+ def create_branch(self, path):
265+ if self.meta.layout == 'single':
266+ return ''
267+
268+ elts = [p for p in path.split('/') if p]
269+ branch_path = self.real_branch(path, False)
270+ if branch_path != None:
271+ return branch_path
272+ elif path.startswith(self.branch_prefix):
273+ branch_path = '/'.join(elts[:3])
274+ else:
275+ branch_path = '/'.join(elts[:-1])
276+ branch_path = '/' + branch_path
277+ if branch_path.startswith(self.branch_prefix):
278+ return branch_path
279+ return None
280+
281+ def add_tag(self, hash, tag, revnum):
282+ if tag in self.meta.tagmap and not self.meta.tagmap[tag]:
283+ return
284+ print("Add tag", tag, revnum)
285+ parent_id = self.meta.get_tag_parent(hash, revnum)
286+ self.added_tags[tag] = parent_id, hash
287+
288+ def add_branch(self, branch_path, open_revision, parent_path, parent_rev, must_add = True):
289+ tag_name = self.is_tag(branch_path)
290+ branch_info = [parent_path, parent_rev, open_revision, True]
291+ from_info = self.exist_branch(branch_path, parent_rev)
292+ if tag_name and from_info is None:
293+ print("Try to create an tag from nothing!", tag_name, branch_info, from_info)
294+ return
295+
296+ self.modified[branch_path] = 0
297+ if branch_path in self.all_branches:
298+ revlist = self.all_branches[branch_path]
299+ if -1 in revlist:
300+ revlist[-1][3] = branch_info[3]
301+ else:
302+ revlist[-1] = branch_info
303+ else:
304+ self.all_branches[branch_path] = {-1:branch_info}
305+
306+ def remove_branch(self, branch_path, close_revision):
307+ self.modified[branch_path] = 0
308+ if branch_path in self.all_branches:
309+ if (-1 not in self.all_branches[branch_path]):
310+ raise Exception('Should contains key -1 in', self.all_branches[branch_path])
311+ branch_info = self.all_branches[branch_path].pop(-1)
312+ self.all_branches[branch_path][close_revision] = branch_info
313+ branch_info = self.exist_branch(branch_path, close_revision, 1)
314+ tag_name = self.get_tag_name(branch_info)
315+ print('Close branch or tag with info', ['tag name:' + str(tag_name), branch_path, close_revision] + branch_info)
316+ if tag_name:
317+ self.update_tags[branch_path] = 'D'
318+ parent_path = self.get_parent(branch_path, close_revision - 1)[0]
319+ self.deleted_tags[tag_name] = self.meta.localname(parent_path), None
320+ else:
321+ branch = self.meta.localname(branch_path)
322+ self.deleted_branches.add(branch)
323+ else:
324+ raise Exception('Remove an unexist branch',branch_path, 'in', self.all_branches)
325+
326+ def exist_branch(self, branch_path, branch_rev, include_state = 0):
327+ '''
328+ include_state = 0 means there is an internval [open,close) contains branch_rev
329+ include_state = 1 means there is an internval [open,close] contains branch_rev
330+ include_state = 2 means if there is an interval [open,close), then just return it.
331+ else return the interval that got the maximal close and also the close <= branch_rev
332+ '''
333+ if branch_path not in self.all_branches.iterkeys():
334+ return None
335+ revlist = self.all_branches[branch_path]
336+ result_revision = None
337+ if include_state == 1 and branch_rev in revlist:
338+ result_revision = branch_rev
339+ elif -1 in revlist and (branch_rev == -1 or revlist[-1][2] <= branch_rev):
340+ result_revision = -1
341+ else:
342+ for close_revision in revlist:
343+ open_revision = revlist[close_revision][2]
344+ if (open_revision <= branch_rev and branch_rev < close_revision):
345+ result_revision = close_revision
346+ break
347+ if result_revision is None and include_state == 2:
348+ result_revision = -2
349+ for close_revision in revlist:
350+ if close_revision <= branch_rev and close_revision > result_revision:
351+ result_revision = close_revision
352+ if result_revision == -2:
353+ result_revision = None
354+ if result_revision is None:
355+ return None
356+ branch_info = list(revlist[result_revision])
357+ branch_info.insert(3, result_revision)
358+ return [branch_path, branch_rev] + branch_info
359+
360+ def get_file_path(self, path, branch_path):
361+ if path == None or branch_path == None:
362+ return ''
363+ return path[len(branch_path) + 1:]
364+
365+
366+class PerfectLayout(RepositoryLayout):
367+ def __init__(self, _log = None, _prefix = None):
368+ if (_log is None or _prefix is None):
369+ return
370+ self.log = _log
371+ self.added_tags, self.deleted_tags = {},{}
372+ self.update_tags = {}
373+ self.deleted_branches = set()
374+ self.subdir = _prefix
375+ self.tag_prefixes = self.subdir + 'tags/'
376+ self.branch_prefixes = self.subdir + 'branches/'
377+ self.init_trunk = self.subdir + 'trunk/'
378+ print('PerfectLayout with log', self.log, self.prefix)
379+
380+ def get_project_prefixes(self, project):
381+ return [""]
382+
383+ def supports_tags(self):
384+ return True
385+
386+ def get_tag_path(self, name, project=""):
387+ """Return the path at which the tag with specified name should be found.
388+
389+ :param name: Name of the tag.
390+ :param project: Optional name of the project the tag is for. Can include slashes.
391+ :return: Path of the tag.
392+ """
393+ raise NotImplementedError
394+
395+ def get_tag_name(self, path, project=""):
396+ """Determine the tag name from a tag path.
397+
398+ :param path: Path inside the repository.
399+ """
400+ raise NotImplementedError
401+
402+ def parse(self, path):
403+ """Parse a path.
404+
405+ :return: Tuple with type ('tag', 'branch'), project name, branch path and path
406+ inside the branch
407+ """
408+
409+ raise svn_errors.NotSvnBranchPath(path)
410+
411+ def get_branches(self, repository, revnum, project=None, pb=None):
412+ """Retrieve a list of paths that refer to branches in a specific revision.
413+
414+ :return: Iterator over tuples with (project, branch path)
415+ """
416+ raise NotImplementedError
417+
418+ def get_tags(self, repository, revnum, project=None, pb=None):
419+ """Retrieve a list of paths that refer to tags in a specific revision.
420+
421+ :return: Iterator over tuples with (project, branch path)
422+ """
423+ raise NotImplementedError
424+
425+ def __repr__(self):
426+ return "%s" % (self.__class__.__name__)
427+
428+ def __str__(self):
429+ return "perfect"
430+
431+ def _is_prefix(self, branches, path, project=None):
432+ if (path == self.prefix):
433+ return True
434+ print('branches', branches, path, project)
435+ for branch in branches:
436+ if branch.startswith("%s/" % path):
437+ return True
438+ return False
439+
440+ def _get_branches(self):
441+ return []
442+
443+ def _get_tags(self):
444+ return []
445+
446+ def is_branch_parent(self, path, project=None):
447+ return self._is_prefix(self._get_branches(), path, project)
448+
449+ def is_tag_parent(self, path, project=None):
450+ print(path)
451+ return self._is_prefix(self._get_tags(), path, project)
452
453=== modified file 'layout/standard.py'
454--- layout/standard.py 2011-05-11 12:48:05 +0000
455+++ layout/standard.py 2011-06-14 12:09:26 +0000
456@@ -330,7 +330,7 @@
457
458 def is_branch(self, path, project=None):
459 for bp in self.branches:
460- if wildcard_matches(path, bp):
461+ if wildcard_matches(path, bp):
462 return True
463 return False
464
465
466=== modified file 'repository.py'
467--- repository.py 2011-06-09 11:29:06 +0000
468+++ repository.py 2011-06-14 12:09:26 +0000
469@@ -659,23 +659,29 @@
470 self.get_config().set_layout(layout)
471 self._layout_source = LAYOUT_SOURCE_CONFIG
472
473- def get_layout(self):
474+ def get_layout(self, layoutname = None, prefix = None):
475 """Determine layout to use for this repository.
476
477 This will use whatever layout the user has specified, or
478 otherwise the layout that was guessed by bzr-svn.
479 """
480- return self.get_layout_source()[0]
481+ return self.get_layout_source(layoutname, prefix)[0]
482
483- def get_layout_source(self):
484+ def get_layout_source(self, layoutname = None, prefix = None):
485 if self._layout is None:
486 self._layout_source = LAYOUT_SOURCE_MAPPING_MANDATED
487 self._layout = self.get_mapping().get_mandated_layout(self)
488 if self._layout is None:
489- layoutname = self.get_config().get_layout()
490+ layoutname = layoutname or self.get_config().get_layout()
491 if layoutname is not None:
492 self._layout_source = LAYOUT_SOURCE_CONFIG
493- self._layout = layout.layout_registry.get(layoutname)()
494+ try:
495+ if layoutname == 'perfect':
496+ self._layout = layout.layout_registry.get(layoutname)(self._log, prefix)
497+ else:
498+ self._layout = layout.layout_registry.get(layoutname)()
499+ except KeyError:
500+ raise bzr_errors.BzrCommandError('No such repository layout %r' % layoutname)
501 if self._layout is None:
502 branches = self.get_config().get_branches()
503 tags = self.get_config().get_tags()

Subscribers

People subscribed via source and target branches