1
# Copyright (C) 2005, 2006 by Aaron Bentley
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.
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.
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
19
from bzrlib.bzrdir import BzrDir
20
import bzrlib.bzrdir as bzrdir
21
from bzrlib.errors import (BzrError,
28
from bzrlib.branch import Branch
29
from bzrlib.commit import Commit, NullCommitReporter
30
from bzrlib.commands import Command
31
from bzrlib.option import _global_option, Option
32
from bzrlib.merge import merge_inner
33
from bzrlib.revision import NULL_REVISION
36
from bzrlib.workingtree import WorkingTree
37
from errors import NoPyBaz
41
from pybaz import NameParser as NameParser
42
from pybaz.backends.baz import null_cmd
45
from fai import iter_new_merges, direct_merges
53
import bzrlib.inventory
57
from progress import *
60
BAZ_IMPORT_ROOT = 'TREE_ROOT'
63
class ImportCommitReporter(NullCommitReporter):
65
def escaped(self, escape_count, message):
66
bzrlib.trace.warning("replaced %d control characters in message" %
69
def add_id(files, id=None):
70
"""Adds an explicit id to a list of files.
72
:param files: the name of the file to add an id to
73
:type files: list of str
74
:param id: tag one file using the specified id, instead of generating id
79
args.extend(["--id", id])
85
def make_archive(name, location):
86
pb_location = pybaz.ArchiveLocation(location)
87
pb_location.create_master(pybaz.Archive(name),
88
pybaz.ArchiveLocationParams())
92
>>> q = test_environ()
95
>>> os.path.exists(os.path.join(q, "home", ".arch-params"))
97
>>> teardown_environ(q)
102
saved_dir = os.getcwdu()
103
tdir = tempfile.mkdtemp(prefix="testdir-")
104
os.environ["HOME"] = os.path.join(tdir, "home")
105
os.mkdir(os.environ["HOME"])
106
arch_dir = os.path.join(tdir, "archive_dir")
107
make_archive("test@example.com", arch_dir)
108
work_dir = os.path.join(tdir, "work_dir")
111
pybaz.init_tree(work_dir, "test@example.com/test--test--0")
112
lib_dir = os.path.join(tdir, "lib_dir")
114
pybaz.register_revision_library(lib_dir)
115
pybaz.set_my_id("Test User<test@example.org>")
118
def add_file(path, text, id):
120
>>> q = test_environ()
121
>>> add_file("path with space", "text", "lalala")
122
>>> tree = pybaz.tree_root(".")
123
>>> inv = list(tree.iter_inventory_ids(source=True, both=True))
124
>>> ("x_lalala", "path with space") in inv
126
>>> teardown_environ(q)
128
file(path, "wb").write(text)
132
def add_dir(path, id):
134
>>> q = test_environ()
135
>>> add_dir("path with\(sp) space", "lalala")
136
>>> tree = pybaz.tree_root(".")
137
>>> inv = list(tree.iter_inventory_ids(source=True, both=True))
138
>>> ("x_lalala", "path with\(sp) space") in inv
140
>>> teardown_environ(q)
145
def teardown_environ(tdir):
149
def timport(tree, summary):
150
msg = tree.log_message()
151
msg["summary"] = summary
154
def commit(tree, summary):
156
>>> q = test_environ()
157
>>> tree = pybaz.tree_root(".")
158
>>> timport(tree, "import")
159
>>> commit(tree, "commit")
160
>>> logs = [str(l.revision) for l in tree.iter_logs()]
164
'test@example.com/test--test--0--base-0'
166
'test@example.com/test--test--0--patch-1'
167
>>> teardown_environ(q)
169
msg = tree.log_message()
170
msg["summary"] = summary
173
def commit_test_revisions():
175
>>> q = test_environ()
176
>>> commit_test_revisions()
177
>>> a = pybaz.Archive("test@example.com")
178
>>> revisions = list(a.iter_revisions("test--test--0"))
181
>>> str(revisions[2])
182
'test@example.com/test--test--0--base-0'
183
>>> str(revisions[1])
184
'test@example.com/test--test--0--patch-1'
185
>>> str(revisions[0])
186
'test@example.com/test--test--0--patch-2'
187
>>> teardown_environ(q)
189
tree = pybaz.tree_root(".")
190
add_file("mainfile", "void main(void){}", "mainfile by aaron")
191
timport(tree, "Created mainfile")
192
file("mainfile", "wb").write("or something like that")
193
commit(tree, "altered mainfile")
194
add_file("ofile", "this is another file", "ofile by aaron")
195
commit(tree, "altered mainfile")
198
def commit_more_test_revisions():
200
>>> q = test_environ()
201
>>> commit_test_revisions()
202
>>> commit_more_test_revisions()
203
>>> a = pybaz.Archive("test@example.com")
204
>>> revisions = list(a.iter_revisions("test--test--0"))
207
>>> str(revisions[0])
208
'test@example.com/test--test--0--patch-3'
209
>>> teardown_environ(q)
211
tree = pybaz.tree_root(".")
212
add_file("trainfile", "void train(void){}", "trainfile by aaron")
213
commit(tree, "altered trainfile")
215
class NoSuchVersion(Exception):
216
def __init__(self, version):
217
Exception.__init__(self, "The version %s does not exist." % version)
218
self.version = version
220
def version_ancestry(version):
222
>>> q = test_environ()
223
>>> commit_test_revisions()
224
>>> version = pybaz.Version("test@example.com/test--test--0")
225
>>> ancestors = version_ancestry(version)
226
>>> str(ancestors[0])
227
'test@example.com/test--test--0--base-0'
228
>>> str(ancestors[1])
229
'test@example.com/test--test--0--patch-1'
230
>>> version = pybaz.Version("test@example.com/test--test--0.5")
231
>>> ancestors = version_ancestry(version)
232
Traceback (most recent call last):
233
NoSuchVersion: The version test@example.com/test--test--0.5 does not exist.
234
>>> teardown_environ(q)
237
revision = version.iter_revisions(reverse=True).next()
238
except StopIteration:
242
if not version.exists():
243
raise NoSuchVersion(version)
246
ancestors = list(revision.iter_ancestors(metoo=True))
250
def get_last_revision(branch):
251
last_patch = branch.last_revision()
253
return arch_revision(last_patch)
254
except NotArchRevision:
256
"Directory \"%s\" already exists, and the last revision is not"
257
" an Arch revision (%s)" % (branch.base, last_patch))
259
def do_branch(br_from, to_location, revision_id):
260
"""Derived from branch in builtins."""
264
os.mkdir(to_location)
266
if e.errno == errno.EEXIST:
267
raise UserError('Target directory "%s" already'
268
' exists.' % to_location)
269
if e.errno == errno.ENOENT:
270
raise UserError('Parent of "%s" does not exist.' %
275
br_from.bzrdir.clone(to_location, revision_id)
276
except NoSuchRevision:
278
msg = "The branch %s has no revision %s." % (from_location,
284
def get_remaining_revisions(output_dir, version, encoding,
285
reuse_history_from=[]):
288
output_exists = os.path.exists(output_dir)
290
# We are starting from an existing directory, figure out what
291
# the current version is
292
branch = Branch.open(output_dir)
293
last_patch, last_encoding = get_last_revision(branch)
294
assert encoding == last_encoding
295
if last_patch is None:
296
if branch.last_revision() != None:
297
raise NotPreviousImport(branch.base)
298
elif version is None:
299
version = last_patch.version
300
elif version is None:
301
raise UserError("No version specified, and directory does not exist.")
304
ancestors = version_ancestry(version)
305
if not output_exists and reuse_history_from != []:
306
for ancestor in reversed(ancestors):
307
if last_patch is not None:
308
# found something to copy
310
# try to grab a copy of ancestor
311
# note that is not optimised: we could look for namespace
312
# transitions and only look for the past after the
314
for history_root in reuse_history_from:
315
possible_source = os.path.join(history_root,
316
map_namespace(ancestor.version))
318
source = Branch.open(possible_source)
319
rev_id = revision_id(ancestor, encoding)
320
if rev_id in source.revision_history():
321
do_branch(source, output_dir, rev_id)
322
last_patch = ancestor
324
except NotBranchError:
326
except NoSuchVersion, e:
327
raise UserError(str(e))
330
for i in range(len(ancestors)):
331
if ancestors[i] == last_patch:
334
raise UserError("Directory \"%s\" already exists, and the last "
335
"revision (%s) is not in the ancestry of %s" %
336
(output_dir, last_patch, version))
337
# Strip off all of the ancestors which are already present
338
# And get a directory starting with the latest ancestor
339
latest_ancestor = ancestors[i]
340
old_revno = Branch.open(output_dir).revno()
341
ancestors = ancestors[i+1:]
342
return ancestors, old_revno
345
###class Importer(object):
348
### Currently this is used as a parameter object, though more behaviour is
352
### def __init__(self, output_dir, version, fast=False,
353
### verbose=False, dry_run=False, max_count=None,
354
### reuse_history_from=[]):
355
### self.output_dir = output_dir
356
### self.version = version
360
def import_version(output_dir, version, encoding, fast=False,
361
verbose=False, dry_run=False, max_count=None,
362
reuse_history_from=[], standalone=True):
364
>>> q = test_environ()
366
Progress bars output to stderr, but doctest does not capture that.
368
>>> old_stderr = sys.stderr
369
>>> sys.stderr = sys.stdout
371
>>> result_path = os.path.join(q, "result")
372
>>> commit_test_revisions()
373
>>> version = pybaz.Version("test@example.com/test--test--0.1")
374
>>> old_ui = bzrlib.ui.ui_factory
375
>>> bzrlib.ui.ui_factory = bzrlib.ui.text.TextUIFactory(
376
... bar_type=bzrlib.progress.DotsProgressBar)
378
>>> import_version('/', version, None, dry_run=True)
379
Traceback (most recent call last):
380
NotPreviousImport: / is not the location of a previous import.
381
>>> import_version(result_path, version, None, dry_run=True)
382
Traceback (most recent call last):
383
UserError: The version test@example.com/test--test--0.1 does not exist.
384
>>> version = pybaz.Version("test@example.com/test--test--0")
385
>>> import_version(result_path, version, None, dry_run=True) #doctest: +ELLIPSIS
386
importing test@example.com/test--test--0 into ...
388
revisions: ..........................................
389
Dry run, not modifying output_dir
391
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
392
importing test@example.com/test--test--0 into ...
394
revisions: .....................................................................
397
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
398
Tree is up-to-date with test@example.com/test--test--0--patch-2
399
>>> commit_more_test_revisions()
400
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
401
importing test@example.com/test--test--0 into ...
402
revisions: ....................................................
405
>>> bzrlib.ui.ui_factory = old_ui
406
>>> sys.stderr = old_stderr
407
>>> teardown_environ(q)
409
progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
412
ancestors, old_revno = get_remaining_revisions(output_dir, version,
415
except NotBranchError, e:
416
raise NotPreviousImport(e.path)
417
if old_revno is None and len(ancestors) == 0:
418
progress_bar.note('Version %s has no revisions.' % version)
420
if len(ancestors) == 0:
421
last_revision, last_encoding = \
422
get_last_revision(Branch.open(output_dir))
423
progress_bar.note('Tree is up-to-date with %s' % last_revision)
426
progress_bar.note("importing %s into %s" % (version, output_dir))
428
tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
429
dir=os.path.dirname(output_dir))
431
wt = WorkingTree.open(output_dir)
432
except (NotBranchError, NoWorkingTree):
435
for result in iter_import_version(output_dir, ancestors, tempdir,
436
pb=progress_bar, encoding=encoding, fast=fast,
437
verbose=verbose, dry_run=dry_run, max_count=max_count,
438
standalone=standalone):
439
show_progress(progress_bar, result)
441
progress_bar.note('Dry run, not modifying output_dir')
444
# Update the working tree of the branch
446
wt = WorkingTree.open(output_dir)
447
except NoWorkingTree:
450
wt.set_last_revision(wt.branch.last_revision())
451
wt.set_root_id(BAZ_IMPORT_ROOT)
456
progress_bar.note('Cleaning up')
457
shutil.rmtree(tempdir)
458
progress_bar.note("Import complete.")
460
progress_bar.finished()
462
class UserError(BzrCommandError):
463
def __init__(self, message):
464
"""Exception to throw when a user makes an impossible request
465
:param message: The message to emit when printing this exception
466
:type message: string
468
BzrCommandError.__init__(self, message)
470
class NotPreviousImport(UserError):
471
def __init__(self, path):
472
UserError.__init__(self, "%s is not the location of a previous import."
476
def revision_id(arch_revision, encoding):
478
Generate a Bzr revision id from an Arch revision id. 'x' in the id
479
designates a revision imported with an experimental algorithm. A number
480
would indicate a particular standardized version.
482
:param arch_revision: The Arch revision to generate an ID for.
484
>>> revision_id(pybaz.Revision("you@example.com/cat--br--0--base-0"), None)
485
'Arch-1:you@example.com%cat--br--0--base-0'
486
>>> revision_id(pybaz.Revision("you@example.com/cat--br--0--base-0"), 'utf-8')
487
'Arch-1-utf-8:you@example.com%cat--br--0--base-0'
492
encoding = '-' + encoding
493
return "Arch-1%s:%s" % (encoding, str(arch_revision).replace('/', '%'))
495
class NotArchRevision(Exception):
496
def __init__(self, revision_id):
497
msg = "The revision id %s does not look like it came from Arch."\
499
Exception.__init__(self, msg)
501
def arch_revision(revision_id):
503
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0"))
504
Traceback (most recent call last):
505
NotArchRevision: The revision id Arch-1:jrandom@example.com%test--test--0 does not look like it came from Arch.
506
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--base-5"))
507
Traceback (most recent call last):
508
NotArchRevision: The revision id Arch-1:jrandom@example.com%test--test--0--base-5 does not look like it came from Arch.
509
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5")[0])
510
'jrandom@example.com/test--test--0--patch-5'
511
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5")[0])
512
'jrandom@example.com/test--test--0--patch-5'
513
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5")[1])
515
>>> str(arch_revision("Arch-1-utf-8:jrandom@example.com%test--test--0--patch-5")[1])
518
if revision_id is None:
520
if revision_id[:7] not in ('Arch-1:', 'Arch-1-'):
521
raise NotArchRevision(revision_id)
524
encoding, arch_name = revision_id[6:].split(':', 1)
525
arch_name = arch_name.replace('%', '/')
529
encoding = encoding[1:]
530
return pybaz.Revision(arch_name), encoding
531
except pybaz.errors.NamespaceError, e:
532
raise NotArchRevision(revision_id)
535
def create_shared_repository(output_dir):
536
bd = bzrdir.BzrDirMetaFormat1().initialize(output_dir)
537
bd.create_repository(shared=True)
539
def create_branch(output_dir):
541
bd = bzrdir.BzrDirMetaFormat1().initialize(output_dir)
542
return bd.create_branch()
545
def create_checkout(source, to_location, revision_id=None):
546
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
547
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
548
return checkout.create_workingtree(revision_id)
551
def create_checkout_metadata(source, to_location, revision_id=None):
552
if revision_id is None:
553
revision_id = source.last_revision()
554
wt = create_checkout(source, to_location, NULL_REVISION)
555
wt.set_last_revision(revision_id)
556
if revision_id not in (NULL_REVISION, None):
557
wt._write_inventory(wt.basis_tree().inventory)
561
def iter_import_version(output_dir, ancestors, tempdir, pb, encoding,
562
fast=False, verbose=False, dry_run=False,
563
max_count=None, standalone=False):
565
log_encoding = 'ascii'
566
if encoding is not None:
567
log_encoding = encoding
569
# Uncomment this for testing, it basically just has baz2bzr only update
570
# 5 patches at a time
572
ancestors = ancestors[:max_count]
574
# Not sure if I want this output. basically it tells you ahead of time
575
# what it is going to do, but then later it tells you as it is doing it.
576
# what probably would be best would be to collapse it into ranges, so that
577
# this gives the simple view, and then later it gives the blow by blow.
579
# print 'Adding the following revisions:'
580
# for a in ancestors:
583
previous_version=None
584
missing_ancestor = None
586
dry_output_dir = os.path.join(tempdir, 'od')
587
if os.path.exists(output_dir):
588
shutil.copytree(output_dir, dry_output_dir)
589
output_dir = dry_output_dir
591
if os.path.exists(output_dir):
592
target_branch = Branch.open(output_dir)
595
wt = BzrDir.create_standalone_workingtree(output_dir)
596
target_branch = wt.branch
598
target_branch = create_branch(output_dir)
600
for i in range(len(ancestors)):
601
revision = ancestors[i]
602
rev_id = revision_id(revision, encoding)
605
version = str(revision.version)
606
if version != previous_version:
607
pb.note('On version: %s' % version)
608
yield Progress(str(revision.patchlevel), i, len(ancestors))
609
previous_version = version
611
yield Progress("revisions", i, len(ancestors))
613
if target_branch.repository.has_revision(rev_id):
614
target_branch.append_revision(rev_id)
617
revdir = os.path.join(tempdir, "rd")
619
tree, baz_inv, log = get_revision(revdir, revision)
620
except pybaz.errors.ExecProblem, e:
621
if ("%s" % e.args).find('could not connect') == -1:
623
missing_ancestor = revision
625
pb.note("unable to access ancestor %s, making into a merge."
628
target_tree = create_checkout_metadata(target_branch, revdir)
629
branch = target_tree.branch
631
old = os.path.join(revdir, ".bzr")
632
new = os.path.join(tempdir, ".bzr")
634
baz_inv, log = apply_revision(tree, revision)
636
target_tree = WorkingTree.open(revdir)
637
branch = target_tree.branch
638
# cached so we can delete the log
640
log_summary = log.summary
641
log_description = log.description
642
is_continuation = log.continuation_of is not None
643
log_creator = log.creator
644
direct_merges = get_direct_merges(revdir, revision, log)
646
timestamp = email.Utils.mktime_tz(log_date + (0,))
647
if log_summary is None:
649
# log_descriptions of None and "" are ignored.
650
if not is_continuation and log_description:
651
log_message = "\n".join((log_summary, log_description))
653
log_message = log_summary
654
target_tree.lock_write()
658
# if we want it to be in revision-history, do that here.
659
target_tree.set_parent_ids(
660
[revision_id(missing_ancestor, encoding)],
661
allow_leftmost_as_ghost=True)
662
missing_ancestor = None
663
for merged_rev in direct_merges:
664
target_tree.add_pending_merge(revision_id(merged_rev,
666
target_tree.set_root_id(BAZ_IMPORT_ROOT)
667
target_tree.set_inventory(baz_inv)
668
commitobj = Commit(reporter=ImportCommitReporter())
669
commitobj.commit(working_tree=target_tree,
670
message=log_message.decode(log_encoding, 'replace'),
671
verbose=False, committer=log_creator, timestamp=timestamp,
672
timezone=0, rev_id=rev_id, revprops={})
676
yield Progress("revisions", len(ancestors), len(ancestors))
678
def get_direct_merges(revdir, revision, log):
679
continuation = log.continuation_of
680
previous_version = revision.version
681
if pybaz.WorkingTree(revdir).tree_version != previous_version:
682
pybaz.WorkingTree(revdir).set_tree_version(previous_version)
683
log_path = "%s/{arch}/%s/%s/%s/%s/patch-log/%s" % (revdir,
684
revision.category.nonarch, revision.branch.nonarch,
685
revision.version.nonarch, revision.archive, revision.patchlevel)
686
temp_path = tempfile.mktemp(dir=os.path.dirname(revdir))
687
os.rename(log_path, temp_path)
688
merges = list(iter_new_merges(revdir, revision.version))
689
direct = direct_merges(merges, [continuation])
690
os.rename(temp_path, log_path)
693
def unlink_unversioned(wt):
694
for unversioned in wt.extras():
695
path = wt.abspath(unversioned)
696
if os.path.isdir(path):
701
def get_log(tree, revision):
702
log = pybaz.Patchlog(revision, tree=tree)
703
assert str(log.revision) == str(revision), (log.revision, revision)
706
def get_revision(revdir, revision):
707
tree = revision.get(revdir)
708
log = get_log(tree, revision)
710
return tree, bzr_inventory_data(tree), log
711
except BadFileKind, e:
712
raise UserError("Cannot convert %s because %s is a %s" %
713
(revision,e.path, e.kind))
716
def apply_revision(tree, revision):
718
log = get_log(tree, revision)
720
return bzr_inventory_data(tree), log
721
except BadFileKind, e:
722
raise UserError("Cannot convert %s because %s is a %s" %
723
(revision,e.path, e.kind))
726
class BadFileKind(Exception):
727
"""The file kind is not permitted in bzr inventories"""
728
def __init__(self, tree_root, path, kind):
729
self.tree_root = tree_root
732
Exception.__init__(self, "File %s is of forbidden type %s" %
733
(os.path.join(tree_root, path), kind))
736
def bzr_inventory_data(tree):
737
inv_iter = tree.iter_inventory_ids(source=True, both=True)
739
for arch_id, path in inv_iter:
740
bzr_file_id = map_file_id(arch_id)
741
inv_map[path] = bzr_file_id
744
for path, file_id in inv_map.iteritems():
745
full_path = os.path.join(tree, path)
746
kind = bzrlib.osutils.file_kind(full_path)
747
if kind not in ("file", "directory", "symlink"):
748
raise BadFileKind(tree, path, kind)
749
parent_dir = os.path.dirname(path)
751
parent_id = inv_map[parent_dir]
753
parent_id = bzrlib.inventory.ROOT_ID
754
bzr_inv.append((path, file_id, parent_id, kind))
759
def baz_import_branch(to_location, from_branch, fast, max_count, verbose,
760
encoding, dry_run, reuse_history_list):
761
to_location = os.path.realpath(str(to_location))
762
if from_branch is not None:
764
from_branch = pybaz.Version(from_branch)
765
except pybaz.errors.NamespaceError:
766
print "%s is not a valid Arch branch." % from_branch
768
if reuse_history_list is None:
769
reuse_history_list = []
770
import_version(to_location, from_branch, encoding, max_count=max_count,
771
reuse_history_from=reuse_history_list)
774
class NotInABranch(Exception):
775
def __init__(self, path):
776
Exception.__init__(self, "%s is not in a branch." % path)
781
def baz_import(to_root_dir, from_archive, encoding, verbose=False,
782
reuse_history_list=[], prefixes=None):
783
if reuse_history_list is None:
784
reuse_history_list = []
785
to_root = str(os.path.realpath(to_root_dir))
786
if not os.path.exists(to_root):
788
if prefixes is not None:
789
prefixes = prefixes.split(':')
790
import_archive(to_root, from_archive, verbose, encoding,
791
reuse_history_list, prefixes=prefixes)
794
def import_archive(to_root, from_archive, verbose,
795
encoding, reuse_history_from=[], standalone=False,
797
def selected(version):
801
for prefix in prefixes:
802
if version.nonarch.startswith(prefix):
805
real_to = os.path.realpath(to_root)
806
history_locations = [real_to] + reuse_history_from
807
if standalone is False:
809
bd = BzrDir.open(to_root)
811
except NotBranchError:
812
create_shared_repository(to_root)
813
except NoRepositoryPresent:
814
raise BzrCommandError("Can't create repository at existing branch.")
815
versions = list(pybaz.Archive(str(from_archive)).iter_versions())
816
progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
818
for num, version in enumerate(versions):
819
progress_bar.update("Branch", num, len(versions))
820
if not selected(version):
821
print "Skipping %s" % version
823
target = os.path.join(to_root, map_namespace(version))
824
if not os.path.exists(os.path.dirname(target)):
825
os.makedirs(os.path.dirname(target))
827
import_version(target, version, encoding,
828
reuse_history_from=reuse_history_from,
829
standalone=standalone)
830
except pybaz.errors.ExecProblem,e:
831
if str(e).find('The requested revision cannot be built.') != -1:
833
"Skipping version %s as it cannot be built due"
834
" to a missing parent archive." % version)
838
if str(e).find('already exists, and the last revision ') != -1:
840
"Skipping version %s as it has had commits made"
841
" since it was converted to bzr." % version)
845
progress_bar.finished()
848
def map_namespace(a_version):
849
a_version = pybaz.Version("%s" % a_version)
850
parser = NameParser(a_version)
851
version = parser.get_version()
852
branch = parser.get_branch()
853
category = parser.get_category()
854
if branch is None or branch == '':
857
return "%s/%s" % (category, branch)
858
return "%s/%s/%s" % (category, version, branch)
861
def map_file_id(file_id):
862
"""Convert a baz file id to a bzr one."""
863
return file_id.replace('%', '%25').replace('/', '%2f')