source: tailor/vcpx/bzr.py @ 917

Revision 917, 5.8 KB checked in by lele@…, 8 years ago (diff)

Implement a BazaarNG specific _addSubtree()
This really makes the difference importing huge trees.

Line 
1# -*- mode: python; coding: utf-8 -*-
2# :Progetto: vcpx -- bazaar-ng support using the bzrlib instead of the frontend
3# :Creato:   Fri Aug 19 01:06:08 CEST 2005
4# :Autore:   Johan Rydberg <jrydberg@gnu.org>
5#            Jelmer Vernooij <jelmer@samba.org>
6# :Licenza:  GNU General Public License
7#
8
9"""
10This module implements the backends for Bazaar-NG.
11"""
12
13__docformat__ = 'reStructuredText'
14
15from source import UpdatableSourceWorkingDir
16from target import SyncronizableTargetWorkingDir, TargetInitializationFailure
17from bzrlib.branch import Branch
18
19class BzrWorkingDir(UpdatableSourceWorkingDir, SyncronizableTargetWorkingDir):
20    ## UpdatableSourceWorkingDir
21
22    def _changesetFromRevision(self, parent, revision):
23        """
24        Generate changeset for the given Bzr revision
25        """
26        from changes import ChangesetEntry, Changeset
27        from datetime import datetime
28        r = parent.get_revision(revision)
29
30        deltatree = parent.get_revision_delta(parent.revision_id_to_revno(revision))
31        entries = []
32
33        for delta in deltatree.added:
34            e = ChangesetEntry(delta[0])
35            e.action_kind = ChangesetEntry.ADDED
36            entries.append(e)
37
38        for delta in deltatree.removed:
39            e = ChangesetEntry(delta[0])
40            e.action_kind = ChangesetEntry.DELETED
41            entries.append(e)
42
43        for delta in deltatree.renamed:
44            e = ChangesetEntry(delta[1])
45            e.action_kind = ChangesetEntry.RENAMED
46            e.old_name = delta[0]
47            entries.append(e)
48
49        for delta in deltatree.modified:
50            e = ChangesetEntry(delta[0])
51            e.action_kind = ChangesetEntry.UPDATED
52            entries.append(e)
53
54        return Changeset(r.revision_id,
55                              datetime.fromtimestamp(r.timestamp),
56                              r.committer,
57                              r.message,
58                              entries)
59
60    def _getUpstreamChangesets(self, sincerev):
61        """
62        See what other revisions exist upstream and return them
63        """
64        parent = Branch.open(self.repository.repository)
65
66        revisions = self._b.missing_revisions(parent)
67
68        changesets = [self._changesetFromRevision(parent, ri) for ri in revisions]
69
70        return changesets
71
72    def _applyChangeset(self, changeset):
73        """
74        Apply given remote revision to workingdir
75        """
76        self._b.append_revision(changeset.revision)
77        return [] # No conflicts for now
78
79    def _checkoutUpstreamRevision(self, revision):
80        """
81        Initial checkout, equivalent of 'bzr branch -r ... '
82        """
83        from bzrlib.clone import copy_branch
84
85        parent = Branch.open(self.repository.repository)
86
87        if revision == "INITIAL":
88            self._b = copy_branch(parent, self.basedir, parent.get_rev_id(1))
89        else:
90            self._b = copy_branch(parent, self.basedir, revision)
91
92        return self._changesetFromRevision(parent, parent.last_revision())
93
94    ## SyncronizableTargetWorkingDir
95
96    def _addPathnames(self, entries):
97        # This method may get invoked several times with the same
98        # entries; and Branch.add complains if a file is already
99        # versioned.  So go through the list and sort out entries that
100        # is already versioned, since there is no need to add them.
101        # Do not try to catch any errors from Branch.add, since the
102        # they are _real_ errors.
103        new_entries = []
104        for e in entries:
105            if not self._b.inventory.has_filename(e):
106                new_entries.extend([e])
107
108        if len(new_entries) == 0:
109            return
110        self._b.add(new_entries)
111
112    def _addSubtree(self, subdir):
113        """
114        Add a whole subtree.
115
116        Use smart_add_branch() to add a whole new subtree to the
117        repository.
118        """
119
120        from os.path import join
121        from bzrlib.add import smart_add_branch
122
123        smart_add_branch(self._b, [join(self.basedir, subdir)], recurse=True)
124
125    def _commit(self, date, author, patchname, changelog=None, entries=None):
126        from time import mktime
127        from binascii import hexlify
128        from re import search
129        from bzrlib.osutils import compact_date, rand_bytes
130
131        logmessage = []
132        if patchname:
133            logmessage.append(patchname)
134        if changelog:
135            logmessage.append(changelog)
136        if logmessage:
137            logmessage = '\n'.join(logmessage)
138        else:
139            logmessage = "Empty changelog"
140        timestamp = int(mktime(date.timetuple()))
141
142        # Guess sane email address
143        email = search("<(.*@.*)>", author)
144        if email:
145            email = email.group(1)
146        else:
147            email = author
148
149        revision_id = "%s-%s-%s" % (email, compact_date(timestamp),
150                                    hexlify(rand_bytes(8)))
151        self._b.commit(logmessage, committer=author,
152                       specific_files=entries, rev_id=revision_id,
153                       verbose=self.repository.project.verbose,
154                       timestamp=timestamp)
155
156    def _removePathnames(self, entries):
157        """Remove a sequence of entries"""
158
159        self._b.remove(entries)
160
161    def _renamePathname(self, oldentry, newentry):
162        """Rename an entry"""
163
164        from os.path import join
165
166        # bzr does the rename itself as well
167        os.rename(join(self.basedir, newentry), join(self.basedir, oldentry))
168
169        self._b.rename_one(oldentry, newentry)
170
171    def _prepareTargetRepository(self):
172        """
173        Create the base directory if it doesn't exist, and the
174        repository as well in the new working directory.
175        """
176
177        from os.path import join, exists
178
179        if not exists(join(self.basedir, self.repository.METADIR)):
180            self._b = Branch.initialize(self.basedir)
181        else:
182            self._b = Branch.open(self.basedir)
Note: See TracBrowser for help on using the repository browser.