source: tailor/vcpx/cg.py @ 782

Revision 782, 5.9 KB checked in by Todd Mokros <tmokros@…>, 8 years ago (diff)

Change ignore file created by Cogito target to .git/info/exclude

RevLine 
[691]1# -*- mode: python; coding: utf-8 -*-
2# :Progetto: vcpx -- Git target (using cogito)
3# :Creato:   Wed 24 ago 2005 18:34:27 EDT
4# :Autore:   Todd Mokros <tmokros@tmokros.net>
5# :Licenza:  GNU General Public License
6#
7
8"""
9This module implements the backend for Git by using Cogito.
10"""
11
12__docformat__ = 'reStructuredText'
13
14from shwrap import ExternalCommand, ReopenableNamedTemporaryFile
15from target import SyncronizableTargetWorkingDir, TargetInitializationFailure
16from source import ChangesetApplicationFailure
17
18class CgWorkingDir(SyncronizableTargetWorkingDir):
19
20    ## SyncronizableTargetWorkingDir
21
22    def _addPathnames(self, names):
23        """
24        Add some new filesystem objects.
25        """
26
27        from os.path import join, isdir
28
29        # Currently git/cogito does not handle directories at all, so filter
30        # them out.
31
32        notdirs = [n for n in names if not isdir(join(self.basedir, n))]
33        if notdirs:
[777]34            cmd = self.repository.command("add")
[691]35            ExternalCommand(cwd=self.basedir, command=cmd).execute(notdirs)
36
37    def __parse_author(self, author):
38        """
39        Parse the author field, returning (name, email)
40        """
41        from email.Utils import parseaddr
42        from target import AUTHOR, HOST
43
44        if author.find('@') > -1:
45            name, email = parseaddr(author)
46        else:
47            name, email = author, ''
48        name = name.strip()
49        email = email.strip()
50        if not name:
51            name = AUTHOR
52        if not email:
53            email = "%s@%s" % (AUTHOR, HOST)
54        return (name, email)
55
56    def _commit(self, date, author, patchname, changelog=None, entries=None):
57        """
58        Commit the changeset.
59        """
60
61        from time import mktime
62        from sys import getdefaultencoding
63        from os import environ
64
65        encoding = ExternalCommand.FORCE_ENCODING or getdefaultencoding()
66
67        logmessage = []
68        if patchname:
69            logmessage.append(patchname.encode(encoding))
70        if changelog:
71            logmessage.append(changelog.encode(encoding))
72
73        env = {}
74        env.update(environ)
75
76        (name, email) = self.__parse_author(author)
77        if name:
78            env['GIT_AUTHOR_NAME']=name
79        if email:
80            env['GIT_AUTHOR_EMAIL']=email
81        if date:
82            env['GIT_AUTHOR_DATE']=str(date)
83        # '-f' flag means we can get empty commits, which
84        # shouldn't be a problem.
[777]85        cmd = self.repository.command("commit", "-f")
[691]86        c = ExternalCommand(cwd=self.basedir, command=cmd)
87
88        c.execute(env=env, input='\n'.join(logmessage))
89        if c.exit_status:
90            raise ChangesetApplicationFailure("%s returned status %d" %
91                                              (str(c), c.exit_status))
92
93    def _removePathnames(self, names):
94        """
95        Remove some filesystem object.
96        """
97
98        from os.path import join, isdir
99        # Currently git does not handle directories at all, so filter
100        # them out.
101
102        notdirs = [n for n in names if not isdir(join(self.basedir, n))]
103        if notdirs:
[777]104            cmd = self.repository.command("rm")
[691]105            c=ExternalCommand(cwd=self.basedir, command=cmd)
106            c.execute(notdirs)
107
108    def _renamePathname(self, oldname, newname):
109        """
110        Rename a filesystem object.
111        """
112        # In the future, we may want to switch to using
113        # git rename, in case renames ever get more support
114        # in git.  It currently just does and add and remove.
115        from os.path import join, isdir
116        from os import walk
117        from dualwd import IGNORED_METADIRS
118
119        if isdir(join(self.basedir, newname)):
120            # Given lack of support for directories in current Git,
121            # loop over all files under the new directory and
122            # do a add/remove on them.
123            skip = len(self.basedir)+len(newname)+2
124            for dir, subdirs, files in walk(join(self.basedir, newname)):
125                prefix = dir[skip:]
126
127                for excd in IGNORED_METADIRS:
128                    if excd in subdirs:
129                        subdirs.remove(excd)
130
131                for f in files:
132                    self._removePathnames([join(oldname, prefix, f)])
133                    self._addPathnames([join(newname, prefix, f)])
134        else:
135            self._removePathnames([oldname])
136            self._addPathnames([newname])
137
138    def _prepareTargetRepository(self):
139        """
140        Execute ``cg init``.
141        """
142
143        from os.path import join, exists
144
145        if not exists(join(self.basedir, self.repository.METADIR)):
[777]146            cmd = self.repository.command("init", "-I")
147            init = ExternalCommand(cwd=self.basedir, command=cmd)
[691]148            init.execute()
149
150            if init.exit_status:
151                raise TargetInitializationFailure(
152                    "%s returned status %s" % (str(init), init.exit_status))
153
154    def _prepareWorkingDirectory(self, source_repo):
155        """
[782]156        Create the .git/info/exclude.
[691]157        """
158
159        from os.path import join
160        from re import escape
161        from dualwd import IGNORED_METADIRS
162
[782]163        # Create the .git/info/exclude file, that contains an
164        # fnmatch per line with metadirs to be skipped.
165        ignore = open(join(self.basedir, self.repository.METADIR,
166                           'info', 'exclude'), 'a')
167        ignore.write('\n')
[691]168        ignore.write('\n'.join(['%s' % md
169                                for md in IGNORED_METADIRS]))
170        ignore.write('\n')
171        if self.logfile.startswith(self.basedir):
172            ignore.write(self.logfile[len(self.basedir)+1:])
173            ignore.write('\n')
174        if self.state_file.filename.startswith(self.basedir):
175            sfrelname = self.state_file.filename[len(self.basedir)+1:]
176            ignore.write(sfrelname)
177            ignore.write('\n')
178            ignore.write(sfrelname+'.journal')
179            ignore.write('\n')
180        ignore.close()
181
Note: See TracBrowser for help on using the repository browser.