21
21
"""
22
22
23
23
from __future__ import absolute_import , unicode_literals
24
+
24
25
import re
25
- import os
26
- import sys
27
26
from hgext .convert .common import NoRepo , commit , converter_source
27
+ from mercurial .util import unlinkpath
28
28
from prcslib import PrcsVersion , PrcsProject , PrcsError
29
29
30
30
# Regular expression pattern that checks for main branches.
@@ -43,7 +43,7 @@ def __init__(self, ui, scm, path, revs=None):
43
43
44
44
try :
45
45
self ._project = PrcsProject (path .decode ())
46
- self ._revisions = self ._project .versions ()
46
+ self ._versions = self ._project .versions ()
47
47
except PrcsError :
48
48
raise NoRepo (b"%s does not look like a PRCS project" % path )
49
49
@@ -66,7 +66,7 @@ def _nearest_ancestor(self, version):
66
66
version = PrcsVersion (version )
67
67
68
68
deleted = False
69
- while self ._revisions [str (version )]['deleted' ]:
69
+ while self ._versions [str (version )]['deleted' ]:
70
70
self .ui .note (version , " is deleted\n " )
71
71
deleted = True
72
72
version = PrcsVersion (version .major (), version .minor () - 1 )
@@ -82,61 +82,81 @@ def getheads(self):
82
82
return all the head versions of the PRCS source
83
83
"""
84
84
last_minors = {}
85
- for key in self ._revisions :
86
- if not self ._revisions [key ]["deleted" ]:
85
+ for key in self ._versions :
86
+ if not self ._versions [key ]["deleted" ]:
87
87
version = PrcsVersion (key )
88
88
if last_minors .get (version .major (), 0 ) < version .minor ():
89
89
last_minors [version .major ()] = version .minor ()
90
90
return map (
91
91
lambda item : str (PrcsVersion (* item )).encode (),
92
92
last_minors .items ())
93
93
94
- def getfile (self , name , version ):
94
+ def getfile (self , name , rev ):
95
95
"""
96
- get the content of a file
96
+ Return the content and mode of a file as a 'tuple' value
97
97
"""
98
- version = version .decode ()
99
- descriptor = self ._descriptor (version )
98
+ if rev is None :
99
+ return None , None
100
+
101
+ rev = rev .decode ()
102
+ descriptor = self ._descriptor (rev )
100
103
files = descriptor .files ()
101
- if name .decode () in files :
102
- attr = files [name .decode ()]
103
- if "symlink" in attr :
104
- return attr ["symlink" ].encode (), b"l"
104
+ if not name .decode () in files :
105
+ self .ui .debug (b"%s not found for %s" % (name , rev .encode ()))
106
+ return None , None
105
107
106
- self ._project .checkout (version , files = [name .decode ()])
108
+ attr = files [name .decode ()]
109
+ if "symlink" in attr :
110
+ return attr ["symlink" ].encode (), b"l"
107
111
112
+ self ._project .checkout (rev , files = [name .decode ()])
113
+
114
+ try :
108
115
with open (name , "rb" ) as stream :
109
116
content = stream .read ()
117
+ finally :
118
+ unlinkpath (name )
110
119
111
- # NOTE: Win32 does not always releases the file name.
112
- if sys .platform != "win32" :
113
- os .unlink (name )
114
- dir = os .path .dirname (name )
115
- if dir :
116
- os .removedirs (dir )
117
-
118
- return content , b"x" if attr ["mode" ] & (0x1 << 6 ) else b""
120
+ return content , b"x" if attr ["mode" ] & (0x1 << 6 ) else b""
119
121
120
- # The file with the specified name was deleted.
121
- return None , None
122
+ def _removedfiles (self , files , parentfiles ):
123
+ """
124
+ Return a (files, copies) tuple for removed or renamed files.
125
+ """
126
+ changes = []
127
+ copies = {}
128
+ pnamebyid = {}
129
+ for pname , pa in parentfiles .items ():
130
+ if pname not in files :
131
+ changes .append ((pname .encode (), None ))
132
+ if "symlink" not in pa :
133
+ pnamebyid [pa ['id' ]] = pname
134
+ # To process renamed files for copies.
135
+ for name , attr in files .items ():
136
+ if not "symlink" in attr and attr ['id' ] in pnamebyid :
137
+ pname = pnamebyid [attr ['id' ]]
138
+ if name != pname :
139
+ self .ui .note (b"%s was renamed to %s\n " % \
140
+ (pname .encode (), name .encode ()))
141
+ copies [name .encode ()] = pname .encode ()
142
+ return changes , copies
122
143
123
144
def getchanges (self , version , full = False ):
124
145
version = version .decode ()
125
- revision = self ._revisions [version ]
126
146
descriptor = self ._descriptor (version )
127
147
128
148
files = []
129
149
copies = {}
130
150
f = descriptor .files ()
131
- p = descriptor .parentversion ()
151
+ parent = descriptor .parent ()
132
152
# Preparing for a deleted parent.
133
- p = self ._nearest_ancestor (p )
134
- if full or p is None :
153
+ parent = self ._nearest_ancestor (parent )
154
+ if full or parent is None :
135
155
# This is the initial checkin so all files are affected.
136
156
for name in f :
137
157
files .append ((name .encode (), version .encode ()))
138
158
else :
139
- pf = self ._descriptor (p ).files ()
159
+ pf = self ._descriptor (parent ).files ()
140
160
# Handling added or changed files.
141
161
for name , a in f .items ():
142
162
if name in pf :
@@ -155,34 +175,22 @@ def getchanges(self, version, full=False):
155
175
else :
156
176
# Added.
157
177
files .append ((name .encode (), version .encode ()))
158
- # Handling deleted or renamed files.
159
- pnamebyid = {}
160
- for pname , pa in pf .items ():
161
- if pname not in f :
162
- # Removed (or renamed).
163
- files .append ((pname .encode (), version .encode ()))
164
- if "symlink" not in pa :
165
- pnamebyid [pa ['id' ]] = pname
166
- # Handling renamed files for copies.
167
- for name , a in f .items ():
168
- if "symlink" not in a and a ['id' ] in pnamebyid :
169
- pname = pnamebyid [a ['id' ]]
170
- if name != pname :
171
- self .ui .note (b"%s was renamed to %s\n " % (pname .encode (), name .encode ()))
172
- copies [name .encode ()] = pname .encode ()
178
+ # To process removed or renamed files.
179
+ removes , copies = self ._removedfiles (f , pf )
180
+ files .extend (removes )
173
181
return files , copies , set ()
174
182
175
183
def getcommit (self , version ):
176
184
version = version .decode ()
177
- revision = self ._revisions [version ]
185
+ revision = self ._versions [version ]
178
186
descriptor = self ._descriptor (version )
179
187
180
188
parents = []
181
- p = descriptor .parentversion ()
189
+ parent = descriptor .parent ()
182
190
# Preparing for a deleted parent.
183
- p = self ._nearest_ancestor (p )
184
- if p is not None :
185
- parents .append (str (p ).encode ())
191
+ parent = self ._nearest_ancestor (parent )
192
+ if not parent is None :
193
+ parents .append (str (parent ).encode ())
186
194
for mp in descriptor .mergeparents ():
187
195
# Preparing for a deleted merge parent.
188
196
mp = self ._nearest_ancestor (mp )
@@ -196,6 +204,12 @@ def getcommit(self, version):
196
204
revision ['author' ].encode (), revision ['date' ].isoformat ().encode (),
197
205
descriptor .message ().encode (), parents , branch )
198
206
207
+ def numcommits (self ):
208
+ """
209
+ Return the number of commits.
210
+ """
211
+ return len (self ._versions )
212
+
199
213
def gettags (self ):
200
214
"""Return an empty dictionary since PRCS has no tags."""
201
215
return {}
0 commit comments