5 # Author: Simon Hausmann <hausmann@kde.org>
6 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
8 # TODO: - support integrations (at least p4i)
9 # - support incremental imports
11 # - instead of reading all files into a variable try to pipe from
12 # - p4 print directly to stdout. need to figure out file size somehow
14 # - support p4 submit (hah!)
15 # - don't hardcode the import to master
17 import os
, string
, sys
, time
19 if len(sys
.argv
) != 2:
20 sys
.stderr
.write("usage: %s //depot/path[@revRange]\n" % sys
.argv
[0]);
21 sys
.stderr
.write("\n example:\n");
22 sys
.stderr
.write(" %s //depot/my/project/ -- to import everything\n");
23 sys
.stderr
.write(" %s //depot/my/project/@1,6 -- to import only from revision 1 to 6\n");
24 sys
.stderr
.write("\n");
25 sys
.stderr
.write(" (a ... is not needed in the path p4 specification, it's added implicitly)\n");
26 sys
.stderr
.write("\n");
32 atIdx
= prefix
.index("@")
33 changeRange
= prefix
[atIdx
:]
34 prefix
= prefix
[0:atIdx
]
38 if not prefix
.endswith("/"):
42 output
= os
.popen("p4 describe %s" % change
).readlines()
46 splitted
= firstLine
.split(" ")
48 author
= author
[:author
.find("@")]
49 tm
= time
.strptime(splitted
[5] + " " + splitted
[6], "%Y/%m/%d %H:%M:%S ")
50 epoch
= int(time
.mktime(tm
))
54 filesSection
= output
.index("Affected files ...\n")
56 sys
.stderr
.write("Change %s doesn't seem to affect any files. Weird.\n" % change
)
57 return [], [], [], [], []
59 differencesSection
= 0
61 differencesSection
= output
.index("Differences ...\n")
63 sys
.stderr
.write("Change %s doesn't seem to have a differences section. Weird.\n" % change
)
64 return [], [], [], [], []
66 log
= output
[2:filesSection
- 1]
68 lines
= output
[filesSection
+ 2:differencesSection
- 1]
74 # chop off "... " and trailing newline
75 line
= line
[4:len(line
) - 1]
77 lastSpace
= line
.rfind(" ")
79 sys
.stderr
.write("trouble parsing line %s, skipping!\n" % line
)
82 operation
= line
[lastSpace
+ 1:]
83 path
= line
[:lastSpace
]
85 if operation
== "delete":
90 return author
, log
, epoch
, changed
, removed
93 return os
.popen("p4 print -q \"%s\"" % path
).read()
95 def stripRevision(path
):
96 hashPos
= path
.rindex("#")
101 output
= os
.popen("p4 users")
103 firstSpace
= line
.index(" ")
104 secondSpace
= line
.index(" ", firstSpace
+ 1)
105 key
= line
[:firstSpace
]
106 email
= line
[firstSpace
+ 1:secondSpace
]
107 openParenPos
= line
.index("(", secondSpace
)
108 closedParenPos
= line
.index(")", openParenPos
)
109 name
= line
[openParenPos
+ 1:closedParenPos
]
111 users
[key
] = name
+ " " + email
118 output
= os
.popen("p4 changes %s...%s" % (prefix
, changeRange
)).readlines()
122 changeNum
= line
.split(" ")[1]
123 changes
.append(changeNum
)
127 sys
.stderr
.write("\n")
129 tz
= - time
.timezone
/ 36
132 for change
in changes
:
133 [ author
, log
, epoch
, changedFiles
, removedFiles
] = describe(change
)
134 sys
.stderr
.write("\rimporting revision %s (%s%%)" % (change
, cnt
* 100 / len(changes
)))
136 # sys.stderr.write("%s\n" % log)
137 # sys.stderr.write("%s\n" % changedFiles)
138 # sys.stderr.write("%s\n" % removedFiles)
140 print "commit refs/heads/master"
142 print "committer %s %s %s" % (users
[author
], epoch
, tz
)
144 print "committer %s <a@b> %s %s" % (author
, epoch
, tz
)
152 for f
in changedFiles
:
153 if not f
.startswith(prefix
):
154 sys
.stderr
.write("\nchanged files: ignoring path %s outside of %s in change %s\n" % (f
, prefix
, change
))
156 relpath
= f
[len(prefix
):]
157 print "M 644 inline %s" % stripRevision(relpath
)
159 print "data %s" % len(data
)
160 sys
.stdout
.write(data
)
163 for f
in removedFiles
:
164 if not f
.startswith(prefix
):
165 sys
.stderr
.write("\ndeleted files: ignoring path %s outside of %s in change %s\n" % (f
, prefix
, change
))
167 relpath
= f
[len(prefix
):]
168 print "D %s" % stripRevision(relpath
)
172 sys
.stderr
.write("\n")