Merge lp:~luoyonggang/bzr-svn/perfect-layout into lp:bzr-svn/1.1
- perfect-layout
- Merge into 1.1
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij (community) | Disapprove | ||
Review via email: mp+64530@code.launchpad.net |
Commit message
Description of the change
There is indent fixup.
Mainly focused on get perfect working with bzr-svn's layout!
Jelmer Vernooij (jelmer) wrote : | # |
Jelmer Vernooij (jelmer) : | # |
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:/
> >
> > 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.
>
> Cheers,
>
> Jelmer
>
> --
> https:/
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
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.
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
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.
> 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:/
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
- 3734. By Yonggang Luo
-
Add it first!
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
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
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/
debug1: Applying options for bazaar.
debug1: Connecting to bazaar.
debug1: Connection established.
debug1: permanently_
debug1: identity file /cygdrive/
debug1: identity file /cygdrive/
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_
3075 [main] ssh 5584 open_stackdumpfile: Dumping stack trace to
ssh.exe.stack
dump
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
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/
> debug1: Applying options for bazaar.
> debug1: Connecting to bazaar.
> debug1: Connection established.
> debug1: permanently_
> debug1: identity file /cygdrive/
> debug1: identity file /cygdrive/
> 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_
> 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
Yonggang Luo (luoyonggang) wrote : | # |
>
>
> > debug1: Enabling compatibility mode for protocol 2.0
> > 4 [main] ssh 5584 exception::handle: Exception:
> > STATUS_
> > 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
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:/
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
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_
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
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_
>
> 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:/
> You are the owner of lp:~luoyonggang/bzr-svn/perfect-layout.
>
--
此致
礼
罗勇刚
Yours
sincerely,
Yonggang Luo
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_
>>
> 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_
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
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
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() |
Hi,
On 14/06/11 12:57, Yonggang Luo wrote: /code.launchpad .net/~luoyongga ng/bzr- svn/perfect- layout/ +merge/ 64530
> 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:/
>
> 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 get_layout( ) and return PerfectLayout( self._log) from there.
registry as it needs to have the LogWalker passed in. Instead, please
add a configuration option for it, look for that option in
Repository.
Cheers,
Jelmer