SvnSource
From Pickwiki
Jump to navigationJump to search
HomePage>>SourceCode>>BasicSource>>SVN>>SvnSource
SVN Source code; once all source is compiled and cataloged, 'SVN -H' will show usage.
* ===================================== SVN ============================================= * @TCL: SVN wrapper, to be run on the UV prompt * ======================================================================================= * 04.Oct.2013 james: Check /released/ folder too when doing STATUS * 20.Dec.2012 james: Add CATALOG * 07.Sep.2012 james: New 'COMMENTS' option to see the latest comment for each program. * 12.May.2011 james: Handle 'DICT/' in release (flist) files. * 10.Aug.2010 james: Add 'COMPILE' option to check a release before it goes out. * 07.Oct.2009 james: Add 'UPDATE'; only add -m if '[[RequiresComment]]'.. IS THIS OK !? * 30.Jun.2009 james: Add '[[CheckReleaseStatus]]' to make sure nothing was committed after * the Release's Revision Number. * 17.Nov.2008 chrisg: Added support for CLEANUP command * 12.Jul.2008 chrisg: Added support for SVN PROPSET command * 22.Apr.2008 manoj: Fixed a bug that limit the length of a new comment to the comment on * line 4 * 11.Apr.2008 jim: Use the line 4 comment for the [[CommitComment]] ONLY IF there's one item. * 11.Feb.2008 jim: [[RequiresFileList]] = @FALSE for DELETE and STATUS; so those still work * if files are in SVN but not in UV. * 14.Jan.2008 manoj: Added DELETE * 10.Jan.2008 manoj: Added revert * 02.Jan.2008 jim: Restructure to improve error handling, etc. * 31.Aug.2007 manoj: Created * ======================================================================================= * $Id: SVN 44131 2013-11-12 02:57:36Z jim $ * ======================================================================================= * * This invokes the svn command, with the proper svn URL and REAL.USER name * * Ex: * * svn commit svn+ssh://[email protected]/opt/svn/dsi[[/Database/Universe/trunk/dsisrc]] * * Trac Reference: http://trac/dsi/wiki/UniverseInSvn * * ======================================================================================= $include RMS.BP EQU.CMDLINE equate SVN$CMD to "/usr/bin/svn" deffun GET.REALUSER( Err ) deffun OPEN.FILE( FILENAME, FLAGS, FILEVAR, ERR.MSG ) username = GET.REALUSER( Err ) ; if Err # '' then stopm Err ;* Err not yet implemented anyway logFile = "log[[/SVN]].LOG" gosub [[ParseCommandLine]] gosub [[PrepareSvnCommand]] if Err # '' then gosub [[DisplayErrors]] end else gosub [[ExecuteSvnCommand]] gosub [[ExecutePostSvnCommands]] end return * ======================================================================================= [[PrepareSvnCommand]]: [[RequiresFileList]] = @FALSE [[RequiresComment]] = @FALSE * Also add svnOp below (in the [[ShowHelp]] ) begin case case svnOp = "COMMENTS" ; [[RequiresFileList]] = @TRUE ;* NOT REALLY AN SVN COMMAND BUT IT'S HANDY ! case svnOp = "BASIC" ; [[RequiresFileList]] = @TRUE ;* NOT REALLY AN SVN COMMAND BUT IT'S HANDY ! case svnOp = "COMPILE" ; [[RequiresFileList]] = @TRUE ;* NOT REALLY AN SVN COMMAND BUT IT'S HANDY ! case svnOp = "CATALOG" ; [[RequiresFileList]] = @TRUE ;* NOT REALLY AN SVN COMMAND BUT IT'S HANDY ! case svnOp = "COMMIT" ; [[RequiresFileList]] = @TRUE ; [[RequiresComment]] = @TRUE case svnOp = "ADD" ; [[RequiresFileList]] = @TRUE case svnOp = "UPDATE" ; [[RequiresFileList]] = @TRUE ;* Is this dangerous !? Just for messed up SVN !?! case svnOp = "DELETE" ; [[RequiresFileList]] = @FALSE ;* Allow delete from SVN with no UV item ? case svnOp = "DIFF" ; [[RequiresFileList]] = @TRUE case svnOp = "INFO" ; [[RequiresFileList]] = @TRUE case svnOp = "LISTS" ; [[RequiresFileList]] = @TRUE ;* NOT REALLY AN SVN COMMAND BUT IT'S HANDY ! case svnOp = "LOG" ; [[RequiresFileList]] = @TRUE case svnOp = "REVERT" ; [[RequiresFileList]] = @TRUE case svnOp = "PROPSET" ; [[RequiresFileList]] = @TRUE if [[PropertyNameAndValue]] = '' then Err = svnOp:" requires -P, see help"; return end else [[PropertyNameAndValue]] = EREPLACE([[PropertyNameAndValue]], "=", " ") end case svnOp = "STATUS" ; * [[FileList]] is NOT required; but use it if it's there. if [[FileList]] = '' then if [[FileName]] # '' then [[FileList]] = [[FileName]] end else [[FileList]] = "DSI.BP DA.BP WEB.BP RMS.BP" end end else Verbose = @TRUE ;* Force Verbose if you list specific items. if Verbose then [[FileList]] := " -v" ;* Always VERBOSE (show lines NOT changed too...) [[CommitComment]] = '' ;* May have been set from '[[ReadRelease]]' ? case svnOp = "CLEANUP" ; [[FileList]] = [[FileName]] case svnOp = "HELP" ; [[FileList]] = downcase([[FileName]]) ;* NO options required; but may have 2nd parameter case 1 Err = "Invalid SVN Operation '":svnOp end case if [[FileErrs]] # '' then crt [[FileErrs]] ; input j if [[RequiresFileList]] then Err = [[FileErrs]] ; if Err # '' then return if [[FileList]] = '' then Err = svnOp:" requires a File and Item name" ; return end if [[RequiresComment]] and [[CommitComment]] = '' then if CMD.NUM.ARGS = 3 then ;* Only 1 file to commit: use it's comment (Tacky ?) : [[FileName]] = CMD.ARG.S<1, 2> [[ItemID]] = CMD.ARG.S<1, 3> open [[FileName]] to File then read [[ProgramItem]] from File, [[ItemID]] then [[CommentLine]] = [[ProgramItem]]<4> [[CommentUser]] = field( [[CommentLine]], ' ', 3 ) [[CommitComment]] = [[CommentLine]][ col2() + 1, 999 ] end else [[CommitComment]] = "" ;* Why would this be ? Throw an error ? end end gosub [[GetCommitComment]] if [[CommitComment]] = "" then Err = "Cannot ":svnOp:" with an empty comment" end return [[ExecuteSvnCommand]]: * Force the username by passing to the "sudo" command below svnCommand = SVN$CMD:' ':downcase(svnOp):' ':[[PropertyNameAndValue]]:' ':[[FileList]] if [[RequiresComment]] and [[CommitComment]] # '' then svnCommand := ' -m "':[[CommitComment]]:'"' end begin case case svnOp = "COMMENTS" ;* Special hack: just to use the code that reads the Release crt crt " (comments are always from the CURRENT version...)" crt [[FileList]] = trim( [[FileList]] ) [[NumFiles]] = dcount([[FileList]], ' ') [[LongestName]] = 0 for N.F = 1 to [[NumFiles]] [[OneProgram]] = field( [[FileList]], ' ', N.F ) if len([[OneProgram]]) > [[LongestName]] then [[LongestName]] = len([[OneProgram]]) next N.F [[NameFmt]] = 'L#':[[LongestName]] for N.F = 1 to [[NumFiles]] [[OneProgram]] = field( [[FileList]], ' ', N.F ) [[ProgramFile]] = field( [[OneProgram]], '/', 1) [[ProgramID]] = field( [[OneProgram]], '/', 2) if not( OPEN.FILE( [[ProgramFile]], '', PROGRAM.FILE, Err ) ) then stopm Err read [[ProgramCode]] from PROGRAM.FILE, [[ProgramID]] else crt "No item named: ":[[ProgramID]] ; return crt [[OneProgram]] [[NameFmt]]:' ':[[ProgramCode]]<4> next N.F crt * Special hack: just to use the code that reads the Release case svnOp = "COMPILE" or svnOp = "BASIC" or svnOp = "CATALOG" [[FileList]] = trim( [[FileList]] ) [[NumFiles]] = dcount([[FileList]], ' ') for N.F = 1 to [[NumFiles]] [[OneProgram]] = field( [[FileList]], ' ', N.F ) convert '/' to ' ' in [[OneProgram]] if svnOp = "COMPILE" or svnOp = "BASIC" then [[TclCommand]] = "BASIC" else [[TclCommand]] = "CATALOG" execute [[TclCommand]]:" ":[[OneProgram]] next N.F case svnOp = "LISTS" ;* Special hack: just to use the code that reads the Release gosub [[SaveProgramLists]] case 1 svnScript = "(cd /u/dsisrc; sudo -u ":username:" ":svnCommand:" )" call APPEND.UNIX.LOG (svnScript, logFile, aulErr) if [[DisplayCmd]] then crt svnScript ; crt input j ; j = upcase(j) if j = 'X' or j = 'Q' then stop end if not([[NoExecute]]) then execute "SH -c \":svnScript:"\" capturing [[SvnResponse]] end [[OutputResponse]] = [[SvnResponse]] convert @FM to char(10) in [[OutputResponse]] crt [[OutputResponse]] end case return [[ExecutePostSvnCommands]]: * Now do anything special we need 'post SVN' : begin case case svnOp = "DIFF" if [[SvnResponse]] = '' then crt "The current version does not differ from what's checked in." ; crt case svnOp = "COMMIT" if [[ReleaseNumber]] # '' then ;* Separate 'if' because [[SvnLine]] will only be defined for -R : if [[SvnLine]] # 0 then ;* Release needs the SVN number: gosub [[AddReleaseNumber]] end end case svnOp = "STATUS" if [[ReleaseNumber]] # '' then ;* [[SvnLine]] will only be defined for -R : gosub [[CheckReleaseStatus]] end end case return [[SaveProgramLists]]: if not(OPEN.FILE("&SAVEDLISTS&", "", SAVEDLISTS.FILE, Err)) then stopm Err [[FileList]] = trim( [[FileList]] ) [[NumFiles]] = dcount([[FileList]], ' ') F.P = 0 ; [[CurrentFile]] = '~' ; [[ItemList]] = '' loop F.P += 1 while F.P <= [[NumFiles]] do [[OneProgram]] = field( [[FileList]], ' ', F.P ) [[ProgramFile]] = field( [[OneProgram]], '/', 1 ) [[ProgramItem]] = field( [[OneProgram]], '/', 2 ) if [[ProgramFile]] # [[CurrentFile]] then gosub [[SaveLastList]] [[CurrentFile]] = [[ProgramFile]] end [[ItemList]]<-1> = [[ProgramItem]] repeat gosub [[SaveLastList]] return [[SaveLastList]]: if [[CurrentFile]] # '~' then [[ListName]] = [[CurrentFile]]:"_":[[ReleaseNumber]] crt "Writing list ":[[ListName]] write [[ItemList]] on SAVEDLISTS.FILE, [[ListName]] [[ItemList]] = '' end return * ======================================================================================= [[AddReleaseNumber]]: [[RevisionNumber]] = '' [[NumResponseLines]] = dcount( [[SvnResponse]], @FM ) for N.R.L = [[NumResponseLines]] to 1 step -1 ;* Go backward since it's at the end: [[ResponseLn]] = [[SvnResponse]]<N.R.L> if [[ResponseLn]][1,18] = "Committed revision" then [[RevisionNumber]] = trim( field([[ResponseLn]][19,999], '.', 1) ) end next N.R.L if [[RevisionNumber]] # '' then [[ReleaseText]]<SvnLine> = "SVN: ":[[RevisionNumber]] convert @FM to char(10) in [[ReleaseText]] * Was "/home/release/":[[ReleaseNumber]]:"/flist" but maybe in 'released' now?: call WRITE.UNIX( [[ReleaseText]], flistPath, Err) end return * SVN STATUS -R xxxx : Check if the SVN # of each item is > the Release's # [[CheckReleaseStatus]]: [[RevisionNumber]] = field( [[ReleaseText]]<SvnLine>, ' ', 2) if [[RevisionNumber]] = '' then return if [[ReleaseLocation]] # '' then crt ; crt [[ReleaseLocation]] ; crt crt ; crt "Checking that each file is before Revision ":[[RevisionNumber]]:'...' ; crt [[NumResponseLines]] = dcount( [[SvnResponse]], @FM ) for N.R.L = 1 to [[NumResponseLines]] [[ResponseLn]] = [[SvnResponse]]<N.R.L> Revs = trim( [[ResponseLn]][12, 9999] ) ;* Kind of a hack ? How else though ? [[LastCommitted]] = field(Revs, ' ', 2) if [[LastCommitted]] > [[RevisionNumber]] then Path = field( Revs, ' ', 4) crt Path:" has a Revision Number (":[[LastCommitted]]:") AFTER this Releases Revision # ":[[RevisionNumber]]:" ! (one-off Commit ?)" end next N.R.L crt return [[DisplayErrors]]: if Err # '' then crt crt 'ERROR ! : ':Err<1> [[NumErrs]] = dcount(Err, @FM) for N.E = 2 to [[NumErrs]] crt ' ':Err<N.E> next N.E crt crt " ('SVN -H' for more info)" crt end return [[ReadRelease]]: [[ReleaseLocation]] = '' flistPath = "/home/release/":[[ReleaseNumber]]:"/flist" call READ.UNIX( [[ReleaseText]], flistPath, Err) if Err # '' then [[ReleaseLocation]] = ' ** RELEASED **' flistPath = "/home/release/released/":[[ReleaseNumber]]:"/flist" call READ.UNIX( [[ReleaseText]], flistPath, Err2) if Err2 # '' then crt Err ; crt Err2 ; input j ; return end Err = '' ;* Must be in 'released'... so we're good. end convert char(10):char(13) to @FM in [[ReleaseText]] [[SvnLine]] = 0 ;* Track the 'SVN:' line to append the # if we are Committing and there's not one already [[NumLines]] = dcount( [[ReleaseText]], @FM ) for N.L = 1 to [[NumLines]] LN = trim( [[ReleaseText]]<N.L> ) begin case case LN[1,2] = '**' and [[CommitComment]] = '' [[CommitComment]] = LN[3, 99999] ;* Special single comment line used for Commit case LN[1,1] = '*' or LN[1,1] = '#' ;* Ignore comments case index(LN, ':', 1) # 0 ;* Handle special tags : if LN[1,4] = "SVN:" then ;* Is this the "SVN:" line ? [[SvnLine]] = N.L ;* Remember where end case LN # '' ;* Finally handle normal lines: Item = LN ; gosub [[AddItem]] end case next N.L return [[AddItem]]: [[FileName]] = field(Item, '/', 1) ; [[ItemID]] = field(Item, '/', 2) open [[FileName]] to File then [[FileList]] := Item:' ' ;* Keep list because some things don't need to be in UV ?: read dummy from File, [[ItemID]] else [[FileErrs]]<-1> = [[ItemID]]:" is not in ":[[FileName]] end end else if [[FileName]] = 'DICT' then ;* Special case: make it act like a BP ? [[FileList]] := Item:' ' ;* Just like above ? end else [[FileErrs]]<-1> = [[FileName]]:" is not a valid BP file/directory." end end return [[GetCommitComment]]: * Add spaces, to allow for the "new" comment to be longer than '[[CommitComment]]'. A MR.IN characteristic. commitLength = len([[CommitComment]]) [[DisplayComment]] = [[CommitComment]]:spaces(100-commitLength) crt "Enter comment:": ; call MR.IN( [[DisplayComment]], '', OUT ) if OUT = "ESC" or OUT = 'HOME' then stop [[CommitComment]] = trim([[DisplayComment]]) return * ======================================================================================= * Set all Option flags and set [[FileList]] and [[FileErrs]]. Note we don't handle the errors * now because some options don't require them anyway. [[ParseCommandLine]]: [[CmdLineOptions]] = "SINGLEPARAM" ;* for -M option call PARSE.CMDLINE( @SENTENCE, mat CMDLINE, [[CmdLineOptions]] ) if CMD.HELP then gosub Help ; stop svnOp = CMD.ARG.S<1, 1> [[FileName]] = CMD.ARG.S<1, 2> locate 'D' in CMD.FLAG.S<1> setting dum then [[DisplayCmd]] = @TRUE else [[DisplayCmd]] = @FALSE locate 'L' in CMD.FLAG.S<1> setting [[SelectListLoc]] then [[SelectListName]] = CMD.PARAM.S<1, [[SelectListLoc]], 1> end else [[SelectListName]] = '' locate 'N' in CMD.FLAG.S<1> setting dum then [[NoExecute]] = @TRUE else [[NoExecute]] = @FALSE locate 'M' in CMD.FLAG.S<1> setting [[MessagePos]] then [[CommitComment]] = CMD.PARAM.S<1, [[MessagePos]], 1> ;* 'SINGLEPARAM' is set so there's only one line end else [[CommitComment]] = '' locate 'R' in CMD.FLAG.S<1> setting [[ReleasePos]] then [[ReleaseNumber]] = CMD.PARAM.S<1, [[ReleasePos]], 1> end else [[ReleaseNumber]] = '' locate 'V' in CMD.FLAG.S<1> setting dum then Verbose = @TRUE else Verbose = @FALSE locate 'P' in CMD.FLAG.S<1> setting [[PropertyNameAndValueLoc]] then [[PropertyNameAndValue]] = CMD.PARAM.S<1, [[PropertyNameAndValueLoc]], 1> end else [[PropertyNameAndValue]] = '' [[FileList]] = "" ;* Space separated; each item is a path from /u/dsisrc : [[FileErrs]] = "" begin case ;* Lots of ways to get the [[FileList]]: case [[ReleaseNumber]] # '' ; gosub [[ReadRelease]] case [[SelectListName]] # '' ;* Use the SELECT list if provided getlist [[SelectListName]] else Err = "Unable to read Select List ": [[SelectListName]] ; return loop while readnext [[ItemID]] do Item = [[FileName]]:'/':[[ItemID]] ; gosub [[AddItem]] repeat case 1 ;* Get the individual files if no "-L" option was specified for N.A = 3 to CMD.NUM.ARGS ;* We get the files as arguments 3 and more Item = [[FileName]]:'/':CMD.ARG.S<1,N.A> ; gosub [[AddItem]] next N.A end case if svnOp = '' then gosub Help return Help: crt 'SVN <command> { <BP_Dir> <item> ... | -L <save-list> | -R <release#> } [-N][-M "message"][-V][-D][-P <[[PropName]]=PropVal>]' crt crt " where <command> is COMPILE, COMMIT, ADD, DELETE, DIFF, INFO, LOG, REVERT, STATUS, HELP, PROPSET. Options:" crt " -N : No Execute; for testing just to see the <command>" crt " -V : Verbose for STATUS; default for listed items; NOT default for 'all' option" crt " -D : Display the <command> before executing it." crt " -P : Add more arguments after <command>, useful for PROPSET (example)" crt crt " For 'COMMIT' when 'M is not used, you will be prompted for a comment if the release has no '**' comment." crt crt "Examples:" crt " SVN COMMIT DSI.BP AR.FREEZE AR.UNFREEZE" crt " SVN COMMIT DSI.BP -L DSI.BP.FLIST" crt " SVN COMMIT -R 570 : Commit EVERY program in Release 570 using the '**' line for the Comment" crt " SVN COMPILE -R 570 : Compile EVERY program in Release 570: NOT REALLY SVN but it's handy!" crt " SVN LISTS -R 570 : Save Select Lists for program files: NOT REALLY SVN but it's handy!" crt " SVN STATUS DSI.BP : Show all uncommitted 'M'odifications, 'D'eletes, 'A'dds, etc." crt " SVN DIFF DSI.BP AR.FREEZE : Show the difference between the local copy and what's in SVN" crt " SVN INFO DSI.BP AR.FREEZE PMTS : Show misc info about what's in SVN" crt " SVN CLEANUP /u/dsisrc[[/DSI]].BP : Execute cleanup on DSI.BP directory (if something is locked, etc)" crt " SVN LOG DSI.BP AR.FREEZE : List of historical changes" crt crt "To add a new file, you need to execute ADD first before Committing (i.e. standard 'svn' procedure):" crt " SVN ADD DSI.BP NEWFILENAME" crt " SVN COMMIT DSI.BP NEWFILENAME" crt crt "To delete a file, you need to execute DELETE first, and then 'commit the delete' (again, standard svn):" crt "(note: this can be used if you get 'Already Exists' errors ? Just backup your files first !)" crt " SVN DELETE DSI.BP ANYFILENAME" crt " SVN COMMIT DSI.BP ANYFILENAME" crt crt "To set properties like svn:keywords: " crt " SVN PROPSET DSI.BP ANYFILENAME -P svn:keywords=Id" crt " SVN PROPSET DSI.BP ANYFILENAME -P svn:keywords=Id Rev Date Author URL" crt crt "To FIX SVN if you get 'Out of Date' errors (!?) :" crt " SVN UPDATE -R 570 : UPDATE EVERY program in Release 570 to the current SVN #" crt " (CAN THIS OVERWRITE YOUR CHANGES !?)" crt crt "For more svn options try: svn -help and svn <command> help" crt "(see also Confluence page: http://intranet.docmagic.com/display/Development/Universe+SVN+Integration)" return