source: tailor/vcpx/bzr.py @ 1033

Revision 1033, 8.6 KB checked in by Ivan Vilata i Balaguer <ivan@…>, 7 years ago (diff)

Small bzr API change in 0.7
I would like to point out an small API change in the Bazaar-NG
development version (0.7pre): the rename_one() method does no
longer belong to Branch, but to WorkingTree? (see
 http://bazaar-ng.org/bzr/bzr.dev/NEWS). This makes Tailor crash under
some renames.

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
18from bzrlib.delta import compare_trees
19
20class BzrWorkingDir(UpdatableSourceWorkingDir, SyncronizableTargetWorkingDir):
21    ## UpdatableSourceWorkingDir
22
23    def _changesetFromRevision(self, parent, revision):
24        """
25        Generate changeset for the given Bzr revision
26        """
27        from changes import ChangesetEntry, Changeset
28        from datetime import datetime
29        r = parent.get_revision(revision)
30
31        deltatree = parent.get_revision_delta(parent.revision_id_to_revno(revision))
32        entries = []
33
34        for delta in deltatree.added:
35            e = ChangesetEntry(delta[0])
36            e.action_kind = ChangesetEntry.ADDED
37            entries.append(e)
38
39        for delta in deltatree.removed:
40            e = ChangesetEntry(delta[0])
41            e.action_kind = ChangesetEntry.DELETED
42            entries.append(e)
43
44        for delta in deltatree.renamed:
45            e = ChangesetEntry(delta[1])
46            e.action_kind = ChangesetEntry.RENAMED
47            e.old_name = delta[0]
48            entries.append(e)
49
50        for delta in deltatree.modified:
51            e = ChangesetEntry(delta[0])
52            e.action_kind = ChangesetEntry.UPDATED
53            entries.append(e)
54
55        return Changeset(r.revision_id,
56                              datetime.fromtimestamp(r.timestamp),
57                              r.committer,
58                              r.message,
59                              entries)
60
61    def _getUpstreamChangesets(self, sincerev):
62        """
63        See what other revisions exist upstream and return them
64        """
65        from bzrlib import fetch
66
67        parent = Branch.open(self.repository.repository)
68        repo = self._getRepo()
69
70        revisions = repo.missing_revisions(parent)
71        fetch.greedy_fetch(repo, parent)
72
73        for ri in revisions:
74            yield self._changesetFromRevision(parent, ri)
75
76    def _applyChangeset(self, changeset):
77        """
78        Apply given remote revision to workingdir
79        """
80        from bzrlib.merge import merge
81
82        repo = self._getRepo()
83        parent = Branch.open(self.repository.repository)
84
85        oldrevno = repo.revno()
86        self.log.info('Applying "%s" to current r%s', changeset.revision,
87                      oldrevno)
88        repo.append_revision(changeset.revision)
89        merge((self.basedir, -1), (self.basedir, oldrevno),
90              check_clean=False, this_dir=self.basedir)
91        self.log.debug("%s updated to %s",
92                       ', '.join([e.name for e in changeset.entries]),
93                       changeset.revision)
94        return [] # No conflicts for now
95
96    def _checkoutUpstreamRevision(self, revision):
97        """
98        Initial checkout, equivalent of 'bzr branch -r ... '
99        """
100        from bzrlib.clone import copy_branch
101
102        parent = Branch.open(self.repository.repository)
103
104        if revision == "INITIAL":
105            revid = parent.get_rev_id(1)
106        elif revision == "HEAD":
107            revid = None
108        else:
109            revid = revision
110
111        self.log.info('Extracting r%s out of "%s" in "%s"...',
112                      revid, parent, self.basedir)
113        self._b = copy_branch(parent, self.basedir, revid)
114
115        return self._changesetFromRevision(parent, revid)
116
117    ## SyncronizableTargetWorkingDir
118
119    def _addPathnames(self, entries):
120        # This method may get invoked several times with the same
121        # entries; and Branch.add complains if a file is already
122        # versioned.  So go through the list and sort out entries that
123        # is already versioned, since there is no need to add them.  A
124        # file can also already have been marked to be added in this
125        # changeset. Remove those files too. Do not try to catch any
126        # errors from Branch.add, since the they are _real_ errors.
127        new_entries = []
128        inv = self._b.get_inventory(self._b.last_revision())
129        added = [new[0] for new in compare_trees(self._b.revision_tree(self._b.last_revision()), self._b.working_tree()).added]
130        for e in entries:
131            if not inv.has_filename(e) and not e in added:
132                new_entries.extend([e])
133            else:
134                self.log.debug('"%s" already in inventory, skipping', e)
135
136        if len(new_entries) == 0:
137            return
138
139        from bzrlib.add import smart_add_tree
140        import os.path
141        self.log.info('Adding %s...', ', '.join(new_entries))
142        smart_add_tree(self._b.working_tree(),[os.path.join(self.basedir,e) for e in new_entries],recurse=False)
143
144    def _addSubtree(self, subdir):
145        """
146        Add a whole subtree.
147
148        Use smart_add_branch() to add a whole new subtree to the
149        repository.
150        """
151
152        from os.path import join
153        from bzrlib.add import smart_add_tree
154
155        self.log.info('Recursively adding directory "%s"...', subdir)
156        smart_add_tree(self._b.working_tree(), [join(self.basedir, subdir)], recurse=True)
157
158    def _commit(self, date, author, patchname, changelog=None, entries=None):
159        from time import mktime
160        from binascii import hexlify
161        from re import search
162        from bzrlib.osutils import compact_date, rand_bytes
163
164        logmessage = []
165        if patchname:
166            logmessage.append(patchname)
167        if changelog:
168            logmessage.append(changelog)
169        if logmessage:
170            self.log.info('Committing "%s"...', logmessage[0])
171            logmessage = '\n'.join(logmessage)
172        else:
173            self.log.info('Committing...')
174            logmessage = "Empty changelog"
175        timestamp = int(mktime(date.timetuple()))
176
177        # Guess sane email address
178        email = search("<(.*@.*)>", author)
179        if email:
180            email = email.group(1)
181        else:
182            email = author
183
184        revision_id = "%s-%s-%s" % (email, compact_date(timestamp),
185                                    hexlify(rand_bytes(8)))
186        self._b.working_tree().commit(logmessage, committer=author,
187                       specific_files=entries, rev_id=revision_id,
188                       verbose=self.repository.projectref().verbose,
189                       timestamp=timestamp)
190
191    def _removePathnames(self, entries):
192        """Remove a sequence of entries"""
193
194        self.log.info('Removing %s...', ', '.join(entries))
195        self._b.working_tree().remove(entries)
196
197    def _renamePathname(self, oldentry, newentry):
198        """Rename an entry"""
199
200        from os import rename
201        from os.path import join
202
203        # bzr does the rename itself as well
204        self.log.debug('Renaming "%s" back to "%s"', newentry, oldentry)
205        rename(join(self.basedir, newentry), join(self.basedir, oldentry))
206
207        self.log.info('Renaming "%s" to "%s"...', oldentry, newentry)
208        self._b.working_tree().rename_one(oldentry, newentry)
209
210    def _prepareTargetRepository(self):
211        """
212        Create the base directory if it doesn't exist, and the
213        repository as well in the new working directory.
214        """
215
216        from os.path import join, exists, split
217        from bzrlib import IGNORE_FILENAME
218
219        if not exists(join(self.basedir, self.repository.METADIR)):
220            ignored = []
221
222            # Omit our own log...
223            logfile = self.repository.projectref().logfile
224            dir, file = split(logfile)
225            if dir == self.basedir:
226                ignored.append(file)
227
228            # ... and state file
229            sfname = self.repository.projectref().state_file.filename
230            dir, file = split(sfname)
231            if dir == self.basedir:
232                ignored.append(file)
233                ignored.append(file+'.old')
234                ignored.append(file+'.journal')
235
236            if ignored:
237                bzrignore = open(join(self.basedir, IGNORE_FILENAME), 'wU')
238                bzrignore.write('\n'.join(ignored))
239
240            self.log.info('Initializing new repository in "%s"...',
241                          self.basedir)
242            self._b = Branch.initialize(self.basedir)
243        else:
244            self._b = Branch.open(self.basedir)
245
246    def _getRepo(self):
247        try:
248            return self._b
249        except AttributeError:
250            self._b = Branch.open(self.basedir)
251            return self._b
Note: See TracBrowser for help on using the repository browser.