1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
1 |
# Copyright (C) 2004, 2005 by Canonical Ltd
|
2 |
||
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
||
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
||
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
17 |
"""Make a copy of an entire branch and all its history.
|
18 |
||
19 |
This is the underlying function for the branch/get/clone commands."""
|
|
20 |
||
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
21 |
# TODO: This could be done *much* more efficiently by just copying
|
22 |
# all the whole weaves and revisions, rather than getting one
|
|
23 |
# revision at a time.
|
|
24 |
||
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
25 |
# TODO: Optionally, after copying, discard any irrelevant information from
|
26 |
# the destination, such as revisions committed after the last one we're interested
|
|
27 |
# in. This needs to apply a weave prune operation (not written yet) to each
|
|
28 |
# weave one by one.
|
|
29 |
||
30 |
# Copying must be done in a way that supports http transports, where we
|
|
31 |
# can't list a directory, and therefore have to rely on information
|
|
32 |
# retrieved from top-level objects whose names we do know.
|
|
33 |
#
|
|
34 |
# In practice this means we first fetch the revision history and ancestry.
|
|
35 |
# These give us a list of all the revisions that need to be fetched. We
|
|
36 |
# also get the inventory weave. We then just need to get a list of all
|
|
37 |
# file-ids ever referenced by this tree. (It might be nice to keep a list
|
|
38 |
# of them directly.) This is done by walking over the inventories of all
|
|
39 |
# copied revisions and accumulating a list of file ids.
|
|
40 |
#
|
|
41 |
# For local branches it is possible to optimize this considerably in two
|
|
42 |
# ways. One is to hardlink the files (if possible and requested), rather
|
|
43 |
# than copying them. Another is to simply list the directory rather than
|
|
44 |
# walking through the inventories to find out what files are present -- but
|
|
45 |
# there it may be better to just be consistent with remote branches.
|
|
46 |
||
1393.1.11
by Martin Pool
- copy_branch creates destination if it doesn't exist |
47 |
import os |
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
48 |
import sys |
49 |
||
1092.2.24
by Robert Collins
merge from martins newformat branch - brings in transport abstraction |
50 |
import bzrlib |
1393.1.10
by Martin Pool
- factor out stereotyped use of merge to build working dir |
51 |
from bzrlib.merge import build_working_dir |
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
52 |
from bzrlib.branch import Branch |
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
53 |
from bzrlib.trace import mutter, note |
54 |
from bzrlib.store import copy_all |
|
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
55 |
|
56 |
def copy_branch(branch_from, to_location, revision=None, basis_branch=None): |
|
57 |
"""Copy branch_from into the existing directory to_location.
|
|
58 |
||
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
59 |
Returns the newly created branch object.
|
60 |
||
61 |
revision
|
|
62 |
If not None, only revisions up to this point will be copied.
|
|
63 |
The head of the new branch will be that revision. Must be a
|
|
64 |
revid or None.
|
|
65 |
||
66 |
to_location -- The destination directory; must either exist and be
|
|
67 |
empty, or not exist, in which case it is created.
|
|
68 |
||
69 |
basis_branch
|
|
70 |
A local branch to copy revisions from, related to branch_from.
|
|
71 |
This is used when branching from a remote (slow) branch, and we have
|
|
72 |
a local branch that might contain some relevant revisions.
|
|
73 |
"""
|
|
74 |
assert isinstance(branch_from, Branch) |
|
75 |
assert isinstance(to_location, basestring) |
|
76 |
if basis_branch is not None: |
|
77 |
note("basis_branch is not supported for fast weave copy yet.") |
|
1185.15.5
by Martin Pool
- clone should be done with the source branch read-locked |
78 |
branch_from.lock_read() |
79 |
try: |
|
80 |
if not (branch_from.weave_store.listable() |
|
81 |
and branch_from.revision_store.listable()): |
|
82 |
return copy_branch_slower(branch_from, to_location, revision, |
|
83 |
basis_branch) |
|
84 |
history = _get_truncated_history(branch_from, revision) |
|
85 |
if not bzrlib.osutils.lexists(to_location): |
|
86 |
os.mkdir(to_location) |
|
87 |
branch_to = Branch.initialize(to_location) |
|
88 |
mutter("copy branch from %s to %s", branch_from, branch_to) |
|
89 |
branch_to.set_root_id(branch_from.get_root_id()) |
|
90 |
branch_to.append_revision(*history) |
|
91 |
_copy_control_weaves(branch_from, branch_to) |
|
92 |
_copy_text_weaves(branch_from, branch_to) |
|
93 |
_copy_revision_store(branch_from, branch_to) |
|
94 |
build_working_dir(to_location) |
|
95 |
branch_to.set_parent(branch_from.base) |
|
96 |
mutter("copied") |
|
97 |
return branch_to |
|
98 |
finally: |
|
99 |
branch_from.unlock() |
|
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
100 |
|
101 |
||
1393.1.23
by Martin Pool
- fix cloning of part of a branch |
102 |
def _get_truncated_history(branch_from, revision): |
103 |
history = branch_from.revision_history() |
|
104 |
if revision is None: |
|
105 |
return history |
|
106 |
try: |
|
107 |
idx = history.index(revision) |
|
108 |
except ValueError: |
|
109 |
raise InvalidRevisionId('revision {%s} is not on the mainline of %s' |
|
110 |
% (revision, branch_from)) |
|
111 |
return history[:idx+1] |
|
112 |
||
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
113 |
def _copy_text_weaves(branch_from, branch_to): |
114 |
copy_all(branch_from.weave_store, branch_to.weave_store) |
|
115 |
||
116 |
||
117 |
def _copy_revision_store(branch_from, branch_to): |
|
118 |
copy_all(branch_from.revision_store, branch_to.revision_store) |
|
119 |
||
120 |
||
121 |
def _copy_control_weaves(branch_from, branch_to): |
|
122 |
to_control = branch_to.control_weaves |
|
123 |
from_control = branch_from.control_weaves |
|
1415
by Robert Collins
remove the ancestry weave file |
124 |
to_control.copy_multi(from_control, ['inventory']) |
1393.1.20
by Martin Pool
- faster branch command that just copies whole weaves without unpacking them |
125 |
|
126 |
||
127 |
def copy_branch_slower(branch_from, to_location, revision=None, basis_branch=None): |
|
128 |
"""Copy branch_from into the existing directory to_location.
|
|
129 |
||
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
130 |
revision
|
131 |
If not None, only revisions up to this point will be copied.
|
|
132 |
The head of the new branch will be that revision. Must be a
|
|
133 |
revid or None.
|
|
134 |
||
1393.1.11
by Martin Pool
- copy_branch creates destination if it doesn't exist |
135 |
to_location -- The destination directory; must either exist and be
|
136 |
empty, or not exist, in which case it is created.
|
|
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
137 |
|
138 |
revno
|
|
139 |
The revision to copy up to
|
|
140 |
||
141 |
basis_branch
|
|
1393.1.12
by Martin Pool
- merge Transport from John into newformat |
142 |
A local branch to copy revisions from, related to branch_from.
|
143 |
This is used when branching from a remote (slow) branch, and we have
|
|
144 |
a local branch that might contain some relevant revisions.
|
|
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
145 |
"""
|
146 |
assert isinstance(branch_from, Branch) |
|
147 |
assert isinstance(to_location, basestring) |
|
1092.2.24
by Robert Collins
merge from martins newformat branch - brings in transport abstraction |
148 |
if not bzrlib.osutils.lexists(to_location): |
1393.1.11
by Martin Pool
- copy_branch creates destination if it doesn't exist |
149 |
os.mkdir(to_location) |
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
150 |
br_to = Branch.initialize(to_location) |
151 |
mutter("copy branch from %s to %s", branch_from, br_to) |
|
152 |
if basis_branch is not None: |
|
153 |
basis_branch.push_stores(br_to) |
|
154 |
br_to.set_root_id(branch_from.get_root_id()) |
|
155 |
if revision is None: |
|
156 |
revision = branch_from.last_revision() |
|
157 |
br_to.update_revisions(branch_from, stop_revision=revision) |
|
1393.1.10
by Martin Pool
- factor out stereotyped use of merge to build working dir |
158 |
build_working_dir(to_location) |
1393.1.5
by Martin Pool
- move copy_branch into bzrlib.clone |
159 |
br_to.set_parent(branch_from.base) |
160 |
mutter("copied") |
|
161 |
return br_to |