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
=== modified file 'commands.py'
--- commands.py 2010-12-26 14:29:55 +0000
+++ commands.py 2011-06-14 12:09:26 +0000
@@ -30,21 +30,14 @@
30 )30 )
3131
3232
33def get_layout(layoutname):33def get_layoutname(layoutname):
34 """Parse layout name and return a layout.34 """Parse layout name and return a normal layout name.
3535
36 :param layout: Name of the layout to retrieve.36 :param layout: Name of the layout to retrieve.
37 """37 """
38 if isinstance(layoutname, unicode):38 if isinstance(layoutname, unicode):
39 layoutname = layoutname.encode("ascii")39 layoutname = layoutname.encode("ascii")
40 from bzrlib.plugins.svn.layout import layout_registry40 return layoutname
41 from bzrlib.errors import BzrCommandError
42
43 try:
44 ret = layout_registry.get(layoutname)()
45 except KeyError:
46 raise BzrCommandError('No such repository layout %r' % layoutname)
47 return ret
4841
4942
50class cmd_svn_import(Command):43class cmd_svn_import(Command):
@@ -70,7 +63,7 @@
70 Option('all',63 Option('all',
71 help='Convert all revisions, even those not in '64 help='Convert all revisions, even those not in '
72 'current branch history.'),65 'current branch history.'),
73 Option('layout', type=get_layout,66 Option('layoutname', type=get_layoutname,
74 help='Repository layout (none, trunk, etc). '67 help='Repository layout (none, trunk, etc). '
75 'Default: auto.'),68 'Default: auto.'),
76 Option('keep',69 Option('keep',
@@ -87,7 +80,7 @@
87 ]80 ]
8881
89 def run(self, from_location, to_location=None, format=None, trees=False,82 def run(self, from_location, to_location=None, format=None, trees=False,
90 standalone=False, layout=None, all=False, prefix=None, keep=False,83 standalone=False, layoutname=None, all=False, prefix=None, keep=False,
91 restore=False, until=None):84 restore=False, until=None):
92 from bzrlib import (85 from bzrlib import (
93 osutils,86 osutils,
@@ -152,25 +145,12 @@
152 from_repos.lock_read()145 from_repos.lock_read()
153 try:146 try:
154 if prefix is not None:147 if prefix is not None:
155 if layout is None:
156 overall_layout = from_repos.get_guessed_layout()
157 else:
158 overall_layout = layout
159 prefix = prefix.strip("/") + "/"148 prefix = prefix.strip("/") + "/"
160 if overall_layout.is_branch(prefix):
161 raise BzrCommandError("%s appears to contain a branch. "
162 "For individual branches, use 'bzr branch'." %
163 from_location)
164 # FIXME: Hint about is_tag()
165 elif overall_layout.is_branch_parent(prefix):
166 self.outf.write("Importing branches with prefix /%s\n" %
167 urlutils.unescape_for_display(prefix, self.outf.encoding))
168 else:
169 raise BzrCommandError("The specified path is inside a branch. "
170 "Specify a different URL or a different repository layout (see also 'bzr help svn-layout').")
171149
172 if (prefix is not None and150 if (prefix is not None and
173 from_repos.transport.check_path(prefix, to_revnum) == NODE_NONE):151 from_repos.transport.check_path(prefix, to_revnum) == NODE_NONE):
152 #TODO:Is this really necessary? because once a branch removed in SVN.
153 #Then SVN won't see it anymore, but it's sill in the history!
174 raise BzrCommandError("Prefix %s does not exist" % prefix)154 raise BzrCommandError("Prefix %s does not exist" % prefix)
175155
176 def filter_branch(branch):156 def filter_branch(branch):
@@ -179,8 +159,10 @@
179 return False159 return False
180 return True160 return True
181161
182 trace.note("Using repository layout: %s",162 layout = from_repos.get_layout(layoutname, prefix)
183 layout or from_repos.get_layout())163 if layoutname is 'perfect':
164 prefix = None
165 trace.note("Using repository layout: %s", layout)
184 convert_repository(from_repos, to_location, layout,166 convert_repository(from_repos, to_location, layout,
185 not standalone, trees, all, format=format,167 not standalone, trees, all, format=format,
186 filter_branch=filter_branch, keep=keep,168 filter_branch=filter_branch, keep=keep,
187169
=== modified file 'layout/__init__.py'
--- layout/__init__.py 2011-06-07 00:39:20 +0000
+++ layout/__init__.py 2011-06-14 12:09:26 +0000
@@ -306,6 +306,9 @@
306layout_registry.register_lazy("itrunk3", "bzrlib.plugins.svn.layout.standard",306layout_registry.register_lazy("itrunk3", "bzrlib.plugins.svn.layout.standard",
307 "InverseTrunkLayout3")307 "InverseTrunkLayout3")
308308
309layout_registry.register_lazy("perfect", "bzrlib.plugins.svn.layout.perfect",
310 "PerfectLayout")
311
309class RepositoryRegistry(registry.Registry):312class RepositoryRegistry(registry.Registry):
310313
311 def get(self, name):314 def get(self, name):
312315
=== added file 'layout/perfect.py'
--- layout/perfect.py 1970-01-01 00:00:00 +0000
+++ layout/perfect.py 2011-06-14 12:09:26 +0000
@@ -0,0 +1,345 @@
1from subvertpy import NODE_DIR
2
3from bzrlib import urlutils
4from bzrlib.plugins.svn import errors as svn_errors
5from bzrlib.plugins.svn.layout import (
6 RepositoryLayout,
7 get_root_paths,
8 wildcard_matches,
9 )
10
11class SVNBranches(object):
12 def __init__(self, _subdir):
13
14
15 def localname_tag(self, path):
16 if self.meta.layout == 'single':
17 return 'tip'
18 default_tag_prefix = self.subdir + 'tags/'
19 if path == self.subdir + 'trunk' or path is None:
20 return 'tip'
21 elif path.startswith(default_tag_prefix):
22 return path[len(default_tag_prefix):]
23 return path
24
25 def remotename_tag(self, tag):
26 if self.meta.layout == 'single':
27 return '/'
28 if tag == 'tip' or tag is None:
29 return self.subdir + 'trunk'
30 elif tag.startswith('/'):
31 return tag
32 return self.subdir + 'tags/' + tag
33
34 def get_tag_name(self, branch_info = None):
35 if self.meta.layout == 'single':
36 return None
37 if not branch_info:
38 return None
39 if not self.exist_branch(branch_info[2], branch_info[3]):
40 return None
41 return self.is_tag(branch_info[0])
42
43 def is_tag(self, branch_path):
44 for tagspath in self.tag_locations:
45 tag_prefix = self.subdir + tagspath + '/'
46 if branch_path.startswith(tag_prefix):
47 return self.localname_tag(branch_path)
48 return None
49
50 def get_paths(self, revision):
51 paths = {}
52 for p,item in revision.paths.iteritems():
53 paths[p] = svn_changes(item)
54 return paths
55
56 def update(self, svn, revision):
57 """
58 Given a revision object, determine changes to branches.
59 """
60 self.added_tags, self.deleted_tags = {},{}
61 self.deleted_branches = set()
62 self.modified = {}
63 if self.meta.layout == 'single':
64 self.modified['/'] = 1
65 self.all_branches = {'/':{-1:['/', 0, 1]}}
66 return
67
68 paths, revnum = self.get_paths(revision), revision.revnum
69 print(paths, revnum)
70 sorted_paths = sorted(paths.keys())
71 current_test_branches = frozenset(self.all_branches.keys())
72 for p in sorted_paths:
73 if paths[p].action != 'D' and paths[p].action != 'R':
74 continue
75 np = p + '/'
76 for branch_path in current_test_branches:
77 if not self.exist_branch(branch_path, revnum):
78 continue
79 if not (branch_path + '/').startswith(np):
80 continue
81 self.remove_branch(branch_path, revnum)
82
83 for p in sorted_paths:
84 copy_from_path = paths[p].copyfrom_path
85 if (copy_from_path is None):
86 continue
87 copy_from_path += '/'
88 parent_rev = paths[p].copyfrom_rev
89 for parent_path in current_test_branches:
90 rn = parent_path + '/'
91 if not rn.startswith(copy_from_path):
92 continue
93 if not self.exist_branch(parent_path, parent_rev):
94 continue
95 suffix = ''
96 if (rn != copy_from_path):
97 suffix = parent_path[len(copy_from_path) - 1:]
98 new_branch_path = p + suffix
99 if self.real_branch(new_branch_path) == new_branch_path:
100 self.add_branch(new_branch_path, revnum, parent_path, parent_rev)
101
102 for p in sorted_paths:
103 new_branch_path = None
104 branch_info = self.get_file_branch(p, revnum)[1]
105 if branch_info is None:
106 new_branch_path = self.create_branch(p)
107 else:
108 self.modified[branch_info[0]] = 1
109 if (paths[p].action == 'D'):
110 continue
111 if self.contains_branch(p, revnum):
112 continue
113
114 # If p is an exist file at in some current opened branch
115
116 #Now, /llvm/branches/Apple/williamson processed at the begining!
117 #Carefully handle there is copyfrom, but the from palce didn't have any branches!
118 cp_from = paths[p].copyfrom_path
119 if ( (cp_from and not cp_from.startswith(self.subdir)
120 and self.real_branch(p) == p
121 and (branch_info == None or branch_info[3] == 0)) #This means copies outside the current subdir
122 or self.exist_branch(p, revnum, 2) != None): #This means there is an branch at path p before:)
123 new_branch_path = p
124
125 if new_branch_path and svn.checkpath(p.lstrip('/'), revnum) == 'd':
126 sub_path = self.get_file_path(p, new_branch_path)
127 parent_path, parent_rev = self.subdir + 'trunk', 0
128 if cp_from:
129 parent_path = cp_from[:len(cp_from) - len(sub_path)]
130 parent_rev = paths[p].copyfrom_rev
131 if sub_path != '':
132 self.modified[new_branch_path] = 1
133 print("Try add branch with ",p , str(new_branch_path) +':' + str(revnum), sub_path, parent_path + ':' + str(parent_rev))
134 self.add_branch(new_branch_path, revnum, parent_path, parent_rev)
135
136 def contains_branch(self, path, revnum):
137 for branch_path, revlist in self.all_branches.iteritems():
138 if not branch_path.startswith(path):
139 continue
140 if -1 in revlist:
141 return True
142 return False
143
144 def real_branch(self, path, ret_original = True):
145 new_path = path + '/'
146 #TODO: We can fitler more, user can specify which folder can't
147 #contains newly created branch:)
148 trunk_suffix = '/trunk/'
149 index = new_path.find("/trunk/")
150 if index == -1:
151 if ret_original:
152 return path
153 return None
154 index = index + len(trunk_suffix)
155 path = new_path[0:index - 1]
156 return path
157
158 def create_branch(self, path):
159 if self.meta.layout == 'single':
160 return ''
161
162 elts = [p for p in path.split('/') if p]
163 branch_path = self.real_branch(path, False)
164 if branch_path != None:
165 return branch_path
166 elif path.startswith(self.branch_prefix):
167 branch_path = '/'.join(elts[:3])
168 else:
169 branch_path = '/'.join(elts[:-1])
170 branch_path = '/' + branch_path
171 if branch_path.startswith(self.branch_prefix):
172 return branch_path
173 return None
174
175 def add_tag(self, hash, tag, revnum):
176 if tag in self.meta.tagmap and not self.meta.tagmap[tag]:
177 return
178 print("Add tag", tag, revnum)
179 parent_id = self.meta.get_tag_parent(hash, revnum)
180 self.added_tags[tag] = parent_id, hash
181
182 def add_branch(self, branch_path, open_revision, parent_path, parent_rev, must_add = True):
183 tag_name = self.is_tag(branch_path)
184 branch_info = [parent_path, parent_rev, open_revision, True]
185 from_info = self.exist_branch(branch_path, parent_rev)
186 if tag_name and from_info is None:
187 print("Try to create an tag from nothing!", tag_name, branch_info, from_info)
188 return
189
190 self.modified[branch_path] = 0
191 if branch_path in self.all_branches:
192 revlist = self.all_branches[branch_path]
193 if -1 in revlist:
194 revlist[-1][3] = branch_info[3]
195 else:
196 revlist[-1] = branch_info
197 else:
198 self.all_branches[branch_path] = {-1:branch_info}
199
200 def remove_branch(self, branch_path, close_revision):
201 self.modified[branch_path] = 0
202 if branch_path in self.all_branches:
203 if (-1 not in self.all_branches[branch_path]):
204 raise Exception('Should contains key -1 in', self.all_branches[branch_path])
205 branch_info = self.all_branches[branch_path].pop(-1)
206 self.all_branches[branch_path][close_revision] = branch_info
207 branch_info = self.exist_branch(branch_path, close_revision, 1)
208 tag_name = self.get_tag_name(branch_info)
209 print('Close branch or tag with info', ['tag name:' + str(tag_name), branch_path, close_revision] + branch_info)
210 if tag_name:
211 self.update_tags[branch_path] = 'D'
212 parent_path = self.get_parent(branch_path, close_revision - 1)[0]
213 self.deleted_tags[tag_name] = self.meta.localname(parent_path), None
214 else:
215 branch = self.meta.localname(branch_path)
216 self.deleted_branches.add(branch)
217 else:
218 raise Exception('Remove an unexist branch',branch_path, 'in', self.all_branches)
219
220 def exist_branch(self, branch_path, branch_rev, include_state = 0):
221 '''
222 include_state = 0 means there is an internval [open,close) contains branch_rev
223 include_state = 1 means there is an internval [open,close] contains branch_rev
224 include_state = 2 means if there is an interval [open,close), then just return it.
225 else return the interval that got the maximal close and also the close <= branch_rev
226 '''
227 if branch_path not in self.all_branches.iterkeys():
228 return None
229 revlist = self.all_branches[branch_path]
230 result_revision = None
231 if include_state == 1 and branch_rev in revlist:
232 result_revision = branch_rev
233 elif -1 in revlist and (branch_rev == -1 or revlist[-1][2] <= branch_rev):
234 result_revision = -1
235 else:
236 for close_revision in revlist:
237 open_revision = revlist[close_revision][2]
238 if (open_revision <= branch_rev and branch_rev < close_revision):
239 result_revision = close_revision
240 break
241 if result_revision is None and include_state == 2:
242 result_revision = -2
243 for close_revision in revlist:
244 if close_revision <= branch_rev and close_revision > result_revision:
245 result_revision = close_revision
246 if result_revision == -2:
247 result_revision = None
248 if result_revision is None:
249 return None
250 branch_info = list(revlist[result_revision])
251 branch_info.insert(3, result_revision)
252 return [branch_path, branch_rev] + branch_info
253
254 def get_file_path(self, path, branch_path):
255 if path == None or branch_path == None:
256 return ''
257 return path[len(branch_path) + 1:]
258
259
260class PerfectLayout(RepositoryLayout):
261 def __init__(self, _log = None, _prefix = None):
262 if (_log is None or _prefix is None):
263 return
264 self.log = _log
265 self.added_tags, self.deleted_tags = {},{}
266 self.update_tags = {}
267 self.deleted_branches = set()
268 self.subdir = _prefix
269 self.tag_prefixes = self.subdir + 'tags/'
270 self.branch_prefixes = self.subdir + 'branches/'
271 self.init_trunk = self.subdir + 'trunk/'
272 print('PerfectLayout with log', self.log, self.prefix)
273
274 def get_project_prefixes(self, project):
275 return [""]
276
277 def supports_tags(self):
278 return True
279
280 def get_tag_path(self, name, project=""):
281 """Return the path at which the tag with specified name should be found.
282
283 :param name: Name of the tag.
284 :param project: Optional name of the project the tag is for. Can include slashes.
285 :return: Path of the tag.
286 """
287 raise NotImplementedError
288
289 def get_tag_name(self, path, project=""):
290 """Determine the tag name from a tag path.
291
292 :param path: Path inside the repository.
293 """
294 raise NotImplementedError
295
296 def parse(self, path):
297 """Parse a path.
298
299 :return: Tuple with type ('tag', 'branch'), project name, branch path and path
300 inside the branch
301 """
302
303 raise svn_errors.NotSvnBranchPath(path)
304
305 def get_branches(self, repository, revnum, project=None, pb=None):
306 """Retrieve a list of paths that refer to branches in a specific revision.
307
308 :return: Iterator over tuples with (project, branch path)
309 """
310 raise NotImplementedError
311
312 def get_tags(self, repository, revnum, project=None, pb=None):
313 """Retrieve a list of paths that refer to tags in a specific revision.
314
315 :return: Iterator over tuples with (project, branch path)
316 """
317 raise NotImplementedError
318
319 def __repr__(self):
320 return "%s" % (self.__class__.__name__)
321
322 def __str__(self):
323 return "perfect"
324
325 def _is_prefix(self, branches, path, project=None):
326 if (path == self.prefix):
327 return True
328 print('branches', branches, path, project)
329 for branch in branches:
330 if branch.startswith("%s/" % path):
331 return True
332 return False
333
334 def _get_branches(self):
335 return []
336
337 def _get_tags(self):
338 return []
339
340 def is_branch_parent(self, path, project=None):
341 return self._is_prefix(self._get_branches(), path, project)
342
343 def is_tag_parent(self, path, project=None):
344 print(path)
345 return self._is_prefix(self._get_tags(), path, project)
0346
=== modified file 'layout/standard.py'
--- layout/standard.py 2011-05-11 12:48:05 +0000
+++ layout/standard.py 2011-06-14 12:09:26 +0000
@@ -330,7 +330,7 @@
330330
331 def is_branch(self, path, project=None):331 def is_branch(self, path, project=None):
332 for bp in self.branches:332 for bp in self.branches:
333 if wildcard_matches(path, bp):333 if wildcard_matches(path, bp):
334 return True334 return True
335 return False335 return False
336336
337337
=== modified file 'repository.py'
--- repository.py 2011-06-09 11:29:06 +0000
+++ repository.py 2011-06-14 12:09:26 +0000
@@ -659,23 +659,29 @@
659 self.get_config().set_layout(layout)659 self.get_config().set_layout(layout)
660 self._layout_source = LAYOUT_SOURCE_CONFIG660 self._layout_source = LAYOUT_SOURCE_CONFIG
661661
662 def get_layout(self):662 def get_layout(self, layoutname = None, prefix = None):
663 """Determine layout to use for this repository.663 """Determine layout to use for this repository.
664664
665 This will use whatever layout the user has specified, or665 This will use whatever layout the user has specified, or
666 otherwise the layout that was guessed by bzr-svn.666 otherwise the layout that was guessed by bzr-svn.
667 """667 """
668 return self.get_layout_source()[0]668 return self.get_layout_source(layoutname, prefix)[0]
669669
670 def get_layout_source(self):670 def get_layout_source(self, layoutname = None, prefix = None):
671 if self._layout is None:671 if self._layout is None:
672 self._layout_source = LAYOUT_SOURCE_MAPPING_MANDATED672 self._layout_source = LAYOUT_SOURCE_MAPPING_MANDATED
673 self._layout = self.get_mapping().get_mandated_layout(self)673 self._layout = self.get_mapping().get_mandated_layout(self)
674 if self._layout is None:674 if self._layout is None:
675 layoutname = self.get_config().get_layout()675 layoutname = layoutname or self.get_config().get_layout()
676 if layoutname is not None:676 if layoutname is not None:
677 self._layout_source = LAYOUT_SOURCE_CONFIG677 self._layout_source = LAYOUT_SOURCE_CONFIG
678 self._layout = layout.layout_registry.get(layoutname)()678 try:
679 if layoutname == 'perfect':
680 self._layout = layout.layout_registry.get(layoutname)(self._log, prefix)
681 else:
682 self._layout = layout.layout_registry.get(layoutname)()
683 except KeyError:
684 raise bzr_errors.BzrCommandError('No such repository layout %r' % layoutname)
679 if self._layout is None:685 if self._layout is None:
680 branches = self.get_config().get_branches()686 branches = self.get_config().get_branches()
681 tags = self.get_config().get_tags()687 tags = self.get_config().get_tags()

Subscribers

People subscribed via source and target branches