11import sys
2+ import os
23
4+ import sorter
35import shell
46from gitFunctions import Commiter
57import shouter
@@ -39,8 +41,9 @@ def createandload(self, stream, componentbaselineentries=[], create=True):
3941 self .load ()
4042
4143 def load (self ):
42- shouter .shout ("Start (re)loading current workspace" )
43- shell .execute ("lscm load -r %s %s --force" % (self .repo , self .workspace ))
44+ command = "lscm load -r %s %s --force" % (self .repo , self .workspace )
45+ shouter .shout ("Start (re)loading current workspace: " + command )
46+ shell .execute (command )
4447 shouter .shout ("Load of workspace finished" )
4548
4649 def setcomponentstobaseline (self , componentbaselineentries , streamuuid ):
@@ -54,14 +57,14 @@ def setcomponentstobaseline(self, componentbaselineentries, streamuuid):
5457 def setnewflowtargets (self , streamuuid ):
5558 shouter .shout ("Set new Flowtargets" )
5659 if not self .hasflowtarget (streamuuid ):
57- shell .execute ("lscm add flowtarget -r %s %s %s"
58- % ( self . repo , self . workspace , streamuuid ))
59- shell . execute ( "lscm set flowtarget -r %s %s --default --current %s"
60- % ( self . repo , self . workspace , streamuuid ) )
60+ shell .execute ("lscm add flowtarget -r %s %s %s" % ( self . repo , self . workspace , streamuuid ))
61+
62+ command = "lscm set flowtarget -r %s %s --default --current %s" % ( self . repo , self . workspace , streamuuid )
63+ shell . execute ( command )
6164
6265 def hasflowtarget (self , streamuuid ):
63- flowtargetlines = shell . getoutput ( "lscm --show-uuid y --show-alias n list flowtargets -r %s %s"
64- % ( self . repo , self . workspace ) )
66+ command = "lscm --show-uuid y --show-alias n list flowtargets -r %s %s" % ( self . repo , self . workspace )
67+ flowtargetlines = shell . getoutput ( command )
6568 for flowtargetline in flowtargetlines :
6669 splittedinformationline = flowtargetline .split ("\" " )
6770 uuidpart = splittedinformationline [0 ].split (" " )
@@ -74,14 +77,39 @@ def recreateoldestworkspace(self):
7477 self .createandload (self .config .earlieststreamname , self .config .initialcomponentbaselines , False )
7578
7679
80+ class Changes :
81+ latest_accept_command = ""
82+
83+ @staticmethod
84+ def discard (* changeentries ):
85+ idstodiscard = Changes ._collectids (changeentries )
86+ shell .execute ("lscm discard --overwrite-uncommitted " + idstodiscard )
87+
88+ @staticmethod
89+ def accept (* changeentries , logpath ):
90+ for changeEntry in changeentries :
91+ shouter .shout ("Accepting: " + changeEntry .tostring ())
92+ revisions = Changes ._collectids (changeentries )
93+ latest_accept_command = "lscm accept -v --overwrite-uncommitted --changes " + revisions
94+ return shell .execute (latest_accept_command , logpath , "a" )
95+
96+ @staticmethod
97+ def _collectids (changeentries ):
98+ ids = ""
99+ for changeentry in changeentries :
100+ ids += " " + changeentry .revision
101+ return ids
102+
103+
77104class ImportHandler :
78105 def __init__ (self , config ):
79106 self .config = config
107+ self .acceptlogpath = config .getlogpath ("accept.txt" )
80108
81109 def getcomponentbaselineentriesfromstream (self , stream ):
82110 filename = self .config .getlogpath ("StreamComponents_" + stream + ".txt" )
83- shell . execute (
84- "lscm --show-alias n --show-uuid y list components -v -r " + self . config . repo + " " + stream , filename )
111+ command = "lscm --show-alias n --show-uuid y list components -v -r " + self . config . repo + " " + stream
112+ shell . execute ( command , filename )
85113 componentbaselinesentries = []
86114 skippedfirstrow = False
87115 islinewithcomponent = 2
@@ -120,33 +148,105 @@ def acceptchangesintoworkspace(self, changeentries):
120148 amountofchanges = len (changeentries )
121149 shouter .shoutwithdate ("Start accepting %s changesets" % amountofchanges )
122150 amountofacceptedchanges = 0
151+ skipnextchangeset = False
152+ reloaded = False
123153 for changeEntry in changeentries :
124154 amountofacceptedchanges += 1
125- revision = changeEntry .revision
126- acceptingmsg = "Accepting: " + changeEntry .comment + " (Date: " + changeEntry .date + " Author: " \
127- + changeEntry .author + " Revision: " + revision + ")"
128- shouter .shout (acceptingmsg )
129- acceptcommand = "lscm accept --changes " + revision + " --overwrite-uncommitted"
130- acceptedsuccesfully = shell .execute (acceptcommand , self .config .getlogpath ("accept.txt" ), "a" ) is 0
155+ if skipnextchangeset :
156+ skipnextchangeset = False
157+ continue
158+ acceptedsuccesfully = Changes .accept (changeEntry , logpath = self .acceptlogpath ) is 0
131159 if not acceptedsuccesfully :
132- shouter .shout ("Last executed command: " + acceptcommand )
133- sys .exit ("Change wasnt succesfully accepted into workspace, please check the output and "
134- "rerun programm with resume" )
160+ shouter .shout ("Change wasnt succesfully accepted into workspace" )
161+ skipnextchangeset = self .retryacceptincludingnextchangeset (changeEntry , changeentries )
162+ elif not reloaded :
163+ if self .is_reloading_necessary ():
164+ WorkspaceHandler (self .config ).load ()
165+ reloaded = True
135166 shouter .shout ("Accepted change %s/%s into working directory" % (amountofacceptedchanges , amountofchanges ))
136167 git .addandcommit (changeEntry )
137168
169+ @staticmethod
170+ def is_reloading_necessary ():
171+ return shell .execute ("git diff --exit-code" ) is 0
172+
173+ def retryacceptincludingnextchangeset (self , change , changes ):
174+ successfull = False
175+ nextchangeentry = self .getnextchangeset (change , changes )
176+ if nextchangeentry and (change .author == nextchangeentry .author or "merge" in nextchangeentry .comment .lower ()):
177+ shouter .shout ("Next changeset: " + nextchangeentry .tostring ())
178+ if input ("Press Enter to try to accept it with next changeset together, press any other key to skip this"
179+ " changeset and continue" ):
180+ return False
181+ Changes .discard (change )
182+ successfull = Changes .accept (change , nextchangeentry , logpath = self .acceptlogpath ) is 0
183+ if not successfull :
184+ Changes .discard (change , nextchangeentry )
185+
186+ if not successfull :
187+ shouter .shout ("Last executed command: \n " + Changes .latest_accept_command )
188+ shouter .shout ("Apropriate git commit command \n " + Commiter .getcommitcommand (change ))
189+ if not input ("Press Enter to continue or any other key to exit the program and rerun it with resume" ):
190+ sys .exit ("Please check the output and rerun programm with resume" )
191+ return successfull
192+
193+ @staticmethod
194+ def getnextchangeset (currentchangeentry , changeentries ):
195+ nextchangeentry = None
196+ nextindex = changeentries .index (currentchangeentry ) + 1
197+ has_next_changeset = nextindex is not len (changeentries )
198+ if has_next_changeset :
199+ nextchangeentry = changeentries [nextindex ]
200+ return nextchangeentry
201+
138202 def getchangeentriesofstreamcomponents (self , componentbaselineentries ):
203+ missingchangeentries = {}
139204 shouter .shout ("Start collecting changeentries" )
140- changeentries = []
205+ changeentriesbycomponentbaselineentry = {}
141206 for componentBaseLineEntry in componentbaselineentries :
142- changeentries .extend (self .getchangeentriesofbaseline (componentBaseLineEntry .baseline ))
143- changeentries .sort (key = lambda change : change .date )
144- return changeentries
207+ changeentries = self .getchangeentriesofbaseline (componentBaseLineEntry .baseline )
208+ for changeentry in changeentries :
209+ missingchangeentries [changeentry .revision ] = changeentry
210+ return missingchangeentries
211+
212+ def readhistory (self , componentbaselineentries , streamname ):
213+ if not self .config .useprovidedhistory :
214+ warning = "Warning - UseProvidedHistory is set to false, merge-conflicts are more likely to happen. \n " \
215+ "For more information see https://github.com/WtfJoke/rtc2git/wiki/Getting-your-History-Files"
216+ shouter .shout (warning )
217+ return None
218+ historyuuids = {}
219+ shouter .shout ("Start reading history files" )
220+ for componentBaseLineEntry in componentbaselineentries :
221+ history = self .gethistory (componentBaseLineEntry .componentname , streamname )
222+ historyuuids [componentBaseLineEntry .component ] = history
223+ return historyuuids
224+
225+ @staticmethod
226+ def getchangeentriestoaccept (missingchangeentries , history ):
227+ changeentriestoaccept = []
228+ if history :
229+ historywithchangeentryobject = {}
230+ for key in history .keys ():
231+ currentuuids = history .get (key )
232+ changeentries = []
233+ for uuid in currentuuids :
234+ changeentry = missingchangeentries .get (uuid )
235+ if changeentry :
236+ changeentries .append (changeentry )
237+ historywithchangeentryobject [key ] = changeentries
238+ changeentriestoaccept = sorter .tosortedlist (historywithchangeentryobject )
239+ else :
240+ changeentriestoaccept .extend (missingchangeentries .values ())
241+ # simple sort by date - same as returned by compare command
242+ changeentriestoaccept .sort (key = lambda change : change .date )
243+ return changeentriestoaccept
145244
146245 @staticmethod
147246 def getchangeentriesfromfile (outputfilename ):
148247 informationseparator = "@@"
149248 changeentries = []
249+
150250 with open (outputfilename , 'r' ) as file :
151251 for line in file :
152252 cleanedline = line .strip ()
@@ -159,14 +259,33 @@ def getchangeentriesfromfile(outputfilename):
159259 comment = splittedlines [3 ].strip ()
160260 date = splittedlines [4 ].strip ()
161261 changeentries .append (ChangeEntry (revision , author , email , date , comment ))
262+
162263 return changeentries
163264
265+ @staticmethod
266+ def getsimplehistoryfromfile (outputfilename ):
267+ revisions = []
268+ if not os .path .isfile (outputfilename ):
269+ shouter .shout ("History file not found: " + outputfilename )
270+ shouter .shout ("Skipping this part of history" )
271+ return revisions
272+
273+ with open (outputfilename , 'r' ) as file :
274+ for line in file :
275+ revisions .append (line .strip ())
276+ revisions .reverse () # to begin by the oldest
277+ return revisions
278+
164279 def getchangeentriesofbaseline (self , baselinetocompare ):
165280 return self .getchangeentriesbytypeandvalue ("baseline" , baselinetocompare )
166281
167282 def getchangeentriesofstream (self , streamtocompare ):
168283 shouter .shout ("Start collecting changes since baseline creation" )
169- return self .getchangeentriesbytypeandvalue ("stream" , streamtocompare )
284+ missingchangeentries = {}
285+ changeentries = self .getchangeentriesbytypeandvalue ("stream" , streamtocompare )
286+ for changeentry in changeentries :
287+ missingchangeentries [changeentry .revision ] = changeentry
288+ return missingchangeentries
170289
171290 def getchangeentriesbytypeandvalue (self , comparetype , value ):
172291 dateformat = "yyyy-MM-dd HH:mm:ss"
@@ -176,6 +295,10 @@ def getchangeentriesbytypeandvalue(self, comparetype, value):
176295 shell .execute (comparecommand , outputfilename )
177296 return ImportHandler .getchangeentriesfromfile (outputfilename )
178297
298+ def gethistory (self , componentname , streamname ):
299+ outputfilename = self .config .gethistorypath ("History_%s_%s.txt" % (componentname , streamname ))
300+ return ImportHandler .getsimplehistoryfromfile (outputfilename )
301+
179302
180303class ChangeEntry :
181304 def __init__ (self , revision , author , email , date , comment ):
@@ -189,6 +312,9 @@ def getgitauthor(self):
189312 authorrepresentation = "%s <%s>" % (self .author , self .email )
190313 return shell .quote (authorrepresentation )
191314
315+ def tostring (self ):
316+ return self .comment + " (Date: " + self .date + ", Author: " + self .author + ", Revision: " + self .revision + ")"
317+
192318
193319class ComponentBaseLineEntry :
194320 def __init__ (self , component , baseline , componentname , baselinename ):
0 commit comments