source: tailor/vcpx/bzr.py @ 1022

Revision 1022, 8.5 KB checked in by Bart Teeuwisse <bart.teeuwisse@…>, 8 years ago (diff)

bzr WorkingTree? fixes

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        self.log.info('Adding %s...', ', '.join(new_entries))
139        self._b.add(new_entries)
140
141    def _addSubtree(self, subdir):
142        """
143        Add a whole subtree.
144
145        Use smart_add_branch() to add a whole new subtree to the
146        repository.
147        """
148
149        from os.path import join
150        from bzrlib.add import smart_add_branch
151
152        self.log.info('Recursively adding directory "%s"...', subdir)
153        smart_add_branch(self._b, [join(self.basedir, subdir)], recurse=True)
154
155    def _commit(self, date, author, patchname, changelog=None, entries=None):
156        from time import mktime
157        from binascii import hexlify
158        from re import search
159        from bzrlib.osutils import compact_date, rand_bytes
160
161        logmessage = []
162        if patchname:
163            logmessage.append(patchname)
164        if changelog:
165            logmessage.append(changelog)
166        if logmessage:
167            self.log.info('Committing "%s"...', logmessage[0])
168            logmessage = '\n'.join(logmessage)
169        else:
170            self.log.info('Committing...')
171            logmessage = "Empty changelog"
172        timestamp = int(mktime(date.timetuple()))
173
174        # Guess sane email address
175        email = search("<(.*@.*)>", author)
176        if email:
177            email = email.group(1)
178        else:
179            email = author
180
181        revision_id = "%s-%s-%s" % (email, compact_date(timestamp),
182                                    hexlify(rand_bytes(8)))
183        self._b.working_tree().commit(logmessage, committer=author,
184                       specific_files=entries, rev_id=revision_id,
185                       verbose=self.repository.projectref().verbose,
186                       timestamp=timestamp)
187
188    def _removePathnames(self, entries):
189        """Remove a sequence of entries"""
190
191        self.log.info('Removing %s...', ', '.join(entries))
192        self._b.working_tree().remove(entries)
193
194    def _renamePathname(self, oldentry, newentry):
195        """Rename an entry"""
196
197        from os import rename
198        from os.path import join
199
200        # bzr does the rename itself as well
201        self.log.debug('Renaming "%s" back to "%s"', newentry, oldentry)
202        rename(join(self.basedir, newentry), join(self.basedir, oldentry))
203
204        self.log.info('Renaming "%s" to "%s"...', oldentry, newentry)
205        self._b.rename_one(oldentry, newentry)
206
207    def _prepareTargetRepository(self):
208        """
209        Create the base directory if it doesn't exist, and the
210        repository as well in the new working directory.
211        """
212
213        from os.path import join, exists, split
214        from bzrlib import IGNORE_FILENAME
215
216        if not exists(join(self.basedir, self.repository.METADIR)):
217            ignored = []
218
219            # Omit our own log...
220            logfile = self.repository.projectref().logfile
221            dir, file = split(logfile)
222            if dir == self.basedir:
223                ignored.append(file)
224
225            # ... and state file
226            sfname = self.repository.projectref().state_file.filename
227            dir, file = split(sfname)
228            if dir == self.basedir:
229                ignored.append(file)
230                ignored.append(file+'.old')
231                ignored.append(file+'.journal')
232
233            if ignored:
234                bzrignore = open(join(self.basedir, IGNORE_FILENAME), 'wU')
235                bzrignore.write('\n'.join(ignored))
236
237            self.log.info('Initializing new repository in "%s"...',
238                          self.basedir)
239            self._b = Branch.initialize(self.basedir)
240        else:
241            self._b = Branch.open(self.basedir)
242
243    def _getRepo(self):
244        try:
245            return self._b
246        except AttributeError:
247            self._b = Branch.open(self.basedir)
248            return self._b
Note: See TracBrowser for help on using the repository browser.