~ubuntu-branches/ubuntu/intrepid/git-core/intrepid-security

« back to all changes in this revision

Viewing changes to git-p4import.py

  • Committer: Package Import Robot
  • Author(s): Gerrit Pape
  • Date: 2007-10-04 08:27:01 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20071004082701-rsd058ontoqz4i30
Tags: 1:1.5.3.4-1
new upstream point release (closes: #445188).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
#
3
 
# This tool is copyright (c) 2006, Sean Estabrooks.
4
 
# It is released under the Gnu Public License, version 2.
5
 
#
6
 
# Import Perforce branches into Git repositories.
7
 
# Checking out the files is done by calling the standard p4
8
 
# client which you must have properly configured yourself
9
 
#
10
 
 
11
 
import marshal
12
 
import os
13
 
import sys
14
 
import time
15
 
import getopt
16
 
 
17
 
from signal import signal, \
18
 
   SIGPIPE, SIGINT, SIG_DFL, \
19
 
   default_int_handler
20
 
 
21
 
signal(SIGPIPE, SIG_DFL)
22
 
s = signal(SIGINT, SIG_DFL)
23
 
if s != default_int_handler:
24
 
   signal(SIGINT, s)
25
 
 
26
 
def die(msg, *args):
27
 
    for a in args:
28
 
        msg = "%s %s" % (msg, a)
29
 
    print "git-p4import fatal error:", msg
30
 
    sys.exit(1)
31
 
 
32
 
def usage():
33
 
    print "USAGE: git-p4import [-q|-v]  [--authors=<file>]  [-t <timezone>]  [//p4repo/path <branch>]"
34
 
    sys.exit(1)
35
 
 
36
 
verbosity = 1
37
 
logfile = "/dev/null"
38
 
ignore_warnings = False
39
 
stitch = 0
40
 
tagall = True
41
 
 
42
 
def report(level, msg, *args):
43
 
    global verbosity
44
 
    global logfile
45
 
    for a in args:
46
 
        msg = "%s %s" % (msg, a)
47
 
    fd = open(logfile, "a")
48
 
    fd.writelines(msg)
49
 
    fd.close()
50
 
    if level <= verbosity:
51
 
        print msg
52
 
 
53
 
class p4_command:
54
 
    def __init__(self, _repopath):
55
 
        try:
56
 
            global logfile
57
 
            self.userlist = {}
58
 
            if _repopath[-1] == '/':
59
 
                self.repopath = _repopath[:-1]
60
 
            else:
61
 
                self.repopath = _repopath
62
 
            if self.repopath[-4:] != "/...":
63
 
                self.repopath= "%s/..." % self.repopath
64
 
            f=os.popen('p4 -V 2>>%s'%logfile, 'rb')
65
 
            a = f.readlines()
66
 
            if f.close():
67
 
                raise
68
 
        except:
69
 
                die("Could not find the \"p4\" command")
70
 
 
71
 
    def p4(self, cmd, *args):
72
 
        global logfile
73
 
        cmd = "%s %s" % (cmd, ' '.join(args))
74
 
        report(2, "P4:", cmd)
75
 
        f=os.popen('p4 -G %s 2>>%s' % (cmd,logfile), 'rb')
76
 
        list = []
77
 
        while 1:
78
 
           try:
79
 
                list.append(marshal.load(f))
80
 
           except EOFError:
81
 
                break
82
 
        self.ret = f.close()
83
 
        return list
84
 
 
85
 
    def sync(self, id, force=False, trick=False, test=False):
86
 
        if force:
87
 
            ret = self.p4("sync -f %s@%s"%(self.repopath, id))[0]
88
 
        elif trick:
89
 
            ret = self.p4("sync -k %s@%s"%(self.repopath, id))[0]
90
 
        elif test:
91
 
            ret = self.p4("sync -n %s@%s"%(self.repopath, id))[0]
92
 
        else:
93
 
            ret = self.p4("sync    %s@%s"%(self.repopath, id))[0]
94
 
        if ret['code'] == "error":
95
 
             data = ret['data'].upper()
96
 
             if data.find('VIEW') > 0:
97
 
                 die("Perforce reports %s is not in client view"% self.repopath)
98
 
             elif data.find('UP-TO-DATE') < 0:
99
 
                 die("Could not sync files from perforce", self.repopath)
100
 
 
101
 
    def changes(self, since=0):
102
 
        try:
103
 
            list = []
104
 
            for rec in self.p4("changes %s@%s,#head" % (self.repopath, since+1)):
105
 
                list.append(rec['change'])
106
 
            list.reverse()
107
 
            return list
108
 
        except:
109
 
            return []
110
 
 
111
 
    def authors(self, filename):
112
 
        f=open(filename)
113
 
        for l in f.readlines():
114
 
            self.userlist[l[:l.find('=')].rstrip()] = \
115
 
                    (l[l.find('=')+1:l.find('<')].rstrip(),l[l.find('<')+1:l.find('>')])
116
 
        f.close()
117
 
        for f,e in self.userlist.items():
118
 
                report(2, f, ":", e[0], "  <", e[1], ">")
119
 
 
120
 
    def _get_user(self, id):
121
 
        if not self.userlist.has_key(id):
122
 
            try:
123
 
                user = self.p4("users", id)[0]
124
 
                self.userlist[id] = (user['FullName'], user['Email'])
125
 
            except:
126
 
                self.userlist[id] = (id, "")
127
 
        return self.userlist[id]
128
 
 
129
 
    def _format_date(self, ticks):
130
 
        symbol='+'
131
 
        name = time.tzname[0]
132
 
        offset = time.timezone
133
 
        if ticks[8]:
134
 
            name = time.tzname[1]
135
 
            offset = time.altzone
136
 
        if offset < 0:
137
 
            offset *= -1
138
 
            symbol = '-'
139
 
        localo = "%s%02d%02d %s" % (symbol, offset / 3600, offset % 3600, name)
140
 
        tickso = time.strftime("%a %b %d %H:%M:%S %Y", ticks)
141
 
        return "%s %s" % (tickso, localo)
142
 
 
143
 
    def where(self):
144
 
        try:
145
 
            return self.p4("where %s" % self.repopath)[-1]['path']
146
 
        except:
147
 
            return ""
148
 
 
149
 
    def describe(self, num):
150
 
        desc = self.p4("describe -s", num)[0]
151
 
        self.msg = desc['desc']
152
 
        self.author, self.email = self._get_user(desc['user'])
153
 
        self.date = self._format_date(time.localtime(long(desc['time'])))
154
 
        return self
155
 
 
156
 
class git_command:
157
 
    def __init__(self):
158
 
        try:
159
 
            self.version = self.git("--version")[0][12:].rstrip()
160
 
        except:
161
 
            die("Could not find the \"git\" command")
162
 
        try:
163
 
            self.gitdir = self.get_single("rev-parse --git-dir")
164
 
            report(2, "gdir:", self.gitdir)
165
 
        except:
166
 
            die("Not a git repository... did you forget to \"git init\" ?")
167
 
        try:
168
 
            self.cdup = self.get_single("rev-parse --show-cdup")
169
 
            if self.cdup != "":
170
 
                os.chdir(self.cdup)
171
 
            self.topdir = os.getcwd()
172
 
            report(2, "topdir:", self.topdir)
173
 
        except:
174
 
            die("Could not find top git directory")
175
 
 
176
 
    def git(self, cmd):
177
 
        global logfile
178
 
        report(2, "GIT:", cmd)
179
 
        f=os.popen('git %s 2>>%s' % (cmd,logfile), 'rb')
180
 
        r=f.readlines()
181
 
        self.ret = f.close()
182
 
        return r
183
 
 
184
 
    def get_single(self, cmd):
185
 
        return self.git(cmd)[0].rstrip()
186
 
 
187
 
    def current_branch(self):
188
 
        try:
189
 
            testit = self.git("rev-parse --verify HEAD")[0]
190
 
            return self.git("symbolic-ref HEAD")[0][11:].rstrip()
191
 
        except:
192
 
            return None
193
 
 
194
 
    def get_config(self, variable):
195
 
        try:
196
 
            return self.git("config --get %s" % variable)[0].rstrip()
197
 
        except:
198
 
            return None
199
 
 
200
 
    def set_config(self, variable, value):
201
 
        try:
202
 
            self.git("config %s %s"%(variable, value) )
203
 
        except:
204
 
            die("Could not set %s to " % variable, value)
205
 
 
206
 
    def make_tag(self, name, head):
207
 
        self.git("tag -f %s %s"%(name,head))
208
 
 
209
 
    def top_change(self, branch):
210
 
        try:
211
 
            a=self.get_single("name-rev --tags refs/heads/%s" % branch)
212
 
            loc = a.find(' tags/') + 6
213
 
            if a[loc:loc+3] != "p4/":
214
 
                raise
215
 
            return int(a[loc+3:][:-2])
216
 
        except:
217
 
            return 0
218
 
 
219
 
    def update_index(self):
220
 
        self.git("ls-files -m -d -o -z | git update-index --add --remove -z --stdin")
221
 
 
222
 
    def checkout(self, branch):
223
 
        self.git("checkout %s" % branch)
224
 
 
225
 
    def repoint_head(self, branch):
226
 
        self.git("symbolic-ref HEAD refs/heads/%s" % branch)
227
 
 
228
 
    def remove_files(self):
229
 
        self.git("ls-files | xargs rm")
230
 
 
231
 
    def clean_directories(self):
232
 
        self.git("clean -d")
233
 
 
234
 
    def fresh_branch(self, branch):
235
 
        report(1, "Creating new branch", branch)
236
 
        self.git("ls-files | xargs rm")
237
 
        os.remove(".git/index")
238
 
        self.repoint_head(branch)
239
 
        self.git("clean -d")
240
 
 
241
 
    def basedir(self):
242
 
        return self.topdir
243
 
 
244
 
    def commit(self, author, email, date, msg, id):
245
 
        self.update_index()
246
 
        fd=open(".msg", "w")
247
 
        fd.writelines(msg)
248
 
        fd.close()
249
 
        try:
250
 
                current = self.get_single("rev-parse --verify HEAD")
251
 
                head = "-p HEAD"
252
 
        except:
253
 
                current = ""
254
 
                head = ""
255
 
        tree = self.get_single("write-tree")
256
 
        for r,l in [('DATE',date),('NAME',author),('EMAIL',email)]:
257
 
            os.environ['GIT_AUTHOR_%s'%r] = l
258
 
            os.environ['GIT_COMMITTER_%s'%r] = l
259
 
        commit = self.get_single("commit-tree %s %s < .msg" % (tree,head))
260
 
        os.remove(".msg")
261
 
        self.make_tag("p4/%s"%id, commit)
262
 
        self.git("update-ref HEAD %s %s" % (commit, current) )
263
 
 
264
 
try:
265
 
    opts, args = getopt.getopt(sys.argv[1:], "qhvt:",
266
 
            ["authors=","help","stitch=","timezone=","log=","ignore","notags"])
267
 
except getopt.GetoptError:
268
 
    usage()
269
 
 
270
 
for o, a in opts:
271
 
    if o == "-q":
272
 
        verbosity = 0
273
 
    if o == "-v":
274
 
        verbosity += 1
275
 
    if o in ("--log"):
276
 
        logfile = a
277
 
    if o in ("--notags"):
278
 
        tagall = False
279
 
    if o in ("-h", "--help"):
280
 
        usage()
281
 
    if o in ("--ignore"):
282
 
        ignore_warnings = True
283
 
 
284
 
git = git_command()
285
 
branch=git.current_branch()
286
 
 
287
 
for o, a in opts:
288
 
    if o in ("-t", "--timezone"):
289
 
        git.set_config("perforce.timezone", a)
290
 
    if o in ("--stitch"):
291
 
        git.set_config("perforce.%s.path" % branch, a)
292
 
        stitch = 1
293
 
 
294
 
if len(args) == 2:
295
 
    branch = args[1]
296
 
    git.checkout(branch)
297
 
    if branch == git.current_branch():
298
 
        die("Branch %s already exists!" % branch)
299
 
    report(1, "Setting perforce to ", args[0])
300
 
    git.set_config("perforce.%s.path" % branch, args[0])
301
 
elif len(args) != 0:
302
 
    die("You must specify the perforce //depot/path and git branch")
303
 
 
304
 
p4path = git.get_config("perforce.%s.path" % branch)
305
 
if p4path == None:
306
 
    die("Do not know Perforce //depot/path for git branch", branch)
307
 
 
308
 
p4 = p4_command(p4path)
309
 
 
310
 
for o, a in opts:
311
 
    if o in ("-a", "--authors"):
312
 
        p4.authors(a)
313
 
 
314
 
localdir = git.basedir()
315
 
if p4.where()[:len(localdir)] != localdir:
316
 
    report(1, "**WARNING** Appears p4 client is misconfigured")
317
 
    report(1, "   for sync from %s to %s" % (p4.repopath, localdir))
318
 
    if ignore_warnings != True:
319
 
        die("Reconfigure or use \"--ignore\" on command line")
320
 
 
321
 
if stitch == 0:
322
 
    top = git.top_change(branch)
323
 
else:
324
 
    top = 0
325
 
changes = p4.changes(top)
326
 
count = len(changes)
327
 
if count == 0:
328
 
    report(1, "Already up to date...")
329
 
    sys.exit(0)
330
 
 
331
 
ptz = git.get_config("perforce.timezone")
332
 
if ptz:
333
 
    report(1, "Setting timezone to", ptz)
334
 
    os.environ['TZ'] = ptz
335
 
    time.tzset()
336
 
 
337
 
if stitch == 1:
338
 
    git.remove_files()
339
 
    git.clean_directories()
340
 
    p4.sync(changes[0], force=True)
341
 
elif top == 0 and branch != git.current_branch():
342
 
    p4.sync(changes[0], test=True)
343
 
    report(1, "Creating new initial commit");
344
 
    git.fresh_branch(branch)
345
 
    p4.sync(changes[0], force=True)
346
 
else:
347
 
    p4.sync(changes[0], trick=True)
348
 
 
349
 
report(1, "processing %s changes from p4 (%s) to git (%s)" % (count, p4.repopath, branch))
350
 
for id in changes:
351
 
    report(1, "Importing changeset", id)
352
 
    change = p4.describe(id)
353
 
    p4.sync(id)
354
 
    if tagall :
355
 
            git.commit(change.author, change.email, change.date, change.msg, id)
356
 
    else:
357
 
            git.commit(change.author, change.email, change.date, change.msg, "import")
358
 
    if stitch == 1:
359
 
        git.clean_directories()
360
 
        stitch = 0
361