/* * CVSGENLOG.CMD - NOSA Administrator V1.10 - cla@clanganke.de - 1999-2008 * * Syntax: CVSLOGGEN.CMD [outputfile] * * An up-to-date working directory is required before using this program ! * Please call this program via: cvsenv [archivename] $GENLOG */ /* First comment is used as help text */ /* CHECKVER */ /* ***** BEGIN LICENSE BLOCK ***** * Version: CDDL 1.0 * * The contents of this file are subject to the COMMON DEVELOPMENT AND * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of * the License at http://www.sun.com/cddl/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is * "netlabs.org Open Source Archive Administrator/Client" * * The Original Distribution Package is named * "netlabs.org Open Source Archive Administrator/Client" * and maintained and distributed by the Initial Developer * and/or netlabs.org only. * * In addition to the CDDL the following applies: * If you modify the Original Code, you may distribute it only * as a part of a distribution package where * - the name of the package, created directories or * OS2.INI entries do not contain any of the terms * - "netlabs.org Open Source Archive" * - "NOSA" * - "NOSAC" * - "NOSAADM" * - neither netlabs.org nor the Initial Developer is stated as * the vendor or originator of the resulting Distribution Package, * which contains the Modified Code. * * The Initial Developer of the Original Code is * netlabs.org: Christian Langanke . * Portions created by the Initial Developer are Copyright (C) 1999-2008 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ SIGNAL ON HALT TitleLine = STRIP(SUBSTR(SourceLine(2), 3)); PARSE VAR TitleLine CmdName'.CMD 'Info Title = CmdName Info env = 'OS2ENVIRONMENT'; TRUE = (1 = 1); FALSE = (0 = 1); Redirection = '> NUL 2>&1'; CrLf = "0d0a"x; '@ECHO OFF' /* OS/2 errorcodes */ ERROR.NO_ERROR = 0; ERROR.INVALID_FUNCTION = 1; ERROR.FILE_NOT_FOUND = 2; ERROR.PATH_NOT_FOUND = 3; ERROR.ACCESS_DENIED = 5; ERROR.NOT_ENOUGH_MEMORY = 8; ERROR.INVALID_FORMAT = 11; ERROR.INVALID_DATA = 13; ERROR.NO_MORE_FILES = 18; ERROR.WRITE_FAULT = 29; ERROR.READ_FAULT = 30; ERROR.GEN_FAILURE = 31; ERROR.INVALID_PARAMETER = 87; ERROR.ENVVAR_NOT_FOUND = 203; GlobalVars = 'Title CmdName env TRUE FALSE Redirection ERROR. CrLf'; SAY; /* show help */ ARG Parm . IF (POS('?', Parm) > 0) THEN DO rc = ShowHelp(); EXIT(ERROR.INVALID_PARAMETER); END; /* load RexxUtil */ CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'; CALL SysLoadFuncs; /* Defaults */ GlobalVars = GlobalVars 'fCleanUp LineDelimiter TmpDir LogHeader Fullname.'; rc = ERROR.NO_ERROR; fDebug = FALSE; fCleanup = TRUE; fNodeleteLog = FALSE; LineDelimiter = "01"x LogHeader = COPIES( '-', 77); TmpDir = VALUE('TMP',,env); User = VALUE('USER',,env); CvsRoot = VALUE('CVSROOT',,env); DO UNTIL (TRUE) /* determine output file */ PARSE ARG ChangelogFile LogFile .; IF (STRIP( ChangelogFile) = '') THEN ChangelogFile = 'Changelog.txt'; /* create temporary outfile */ TmpFile = SysTempFileName( TmpDir'\cvslog.???'); rc = LINEOUT( TmpFile); /* check parms */ IF (User = '') THEN DO SAY CmdName': error: environment variable USER not set.'; rc = ERROR.ENVVAR_NOT_FOUND; LEAVE; END; IF (CvsRoot = '') THEN DO SAY CmdName': error: environment variable CVSROOT not set.'; rc = ERROR.ENVVAR_NOT_FOUND; LEAVE; END; /* determine root dir of archive */ SELECT WHEN ( POS(':pserver:', CvsRoot) = 1) THEN PARSE VAR CvsRoot 'pserver:'account':'CvsRoot; WHEN ( POS(':local:', CvsRoot) = 1) THEN PARSE VAR CvsRoot ':local:'CvsRoot; OTHERWISE NOP; END; /* determine fullname list file */ /* and store it to a stem */ Fullname. = ''; FullnamesList = GetCallDir()'\..\config\fullnames.lst'; IF (FileExist( FullnamesList)) THEN DO CALL CHAROUT, 'Reading mail address list ... '; DO WHILE (LINES( FullnamesList) > 0) ThisLine = LINEIN( FullnamesList); IF (ThisLine = '') THEN ITERATE; PARSE VAR ThisLine UserId UserFullName Fullname.Userid = STRIP(UserFullName); END; rc = STREAM( FullnamesList, 'C', 'CLOSE'); SAY 'Ok.'; END; /* current datetime */ NowStamp = TRANSLATE( 'abcd-ef-gh', DATE('S'), 'abcdefgh')' 'TIME(); LogRange = 'from start to' NowStamp; /* log file given ? */ LogFile = STRIP( LogFile); IF (LogFile \= '') THEN fNodeleteLog = TRUE; ELSE DO /* read last log date and time from existing changelog */ LogStamp = ReadLastChangeLogStamp( ChangeLogFile); IF (LogStamp = '') THEN DO CvsRange = '<' NowStamp; END; ELSE DO CvsRange = LogStamp '<' NowStamp; LogRange = 'from' LogStamp 'to' NowStamp; END; /* generate log */ CALL CHAROUT, 'Generating log output ... '; LogFile = SysTempFileName( TmpDir'\cvslog.???'); 'cvs -q log -d "'CvsRange'" . >' LogFile SAY 'Ok.'; END; /* read in log entries */ rc = ReadCvsLogEntries( LogFile, TmpFile); IF (rc \= ERROR.NO_ERROR) THEN LEAVE; /* write change log */ rc = WriteChangeLog( ChangeLogFile, TmpFile, User, LogRange, CvsRoot); IF (rc \= ERROR.NO_ERROR) THEN LEAVE; END; /* cleanup */ IF (fCleanup) THEN DO IF (\fNodeleteLog) THEN rcx = SysFileDelete( LogFile); END; /* exit */ EXIT( rc); /* ------------------------------------------------------------------------- */ HALT: SAY; SAY 'Interrupted by user.'; EXIT(ERROR.GEN_FAILURE); /* ------------------------------------------------------------------------- */ ShowHelp: PROCEDURE EXPOSE (GlobalVars) SAY Title; SAY; PARSE SOURCE . . ThisFile DO i = 1 TO 3 rc = LINEIN(ThisFile); END; ThisLine = LINEIN(Thisfile); DO WHILE (ThisLine \= ' */') SAY SUBSTR(ThisLine, 7); ThisLine = LINEIN(Thisfile); END; rc = LINEOUT(Thisfile); RETURN(''); /* ------------------------------------------------------------------------- */ FileExist: PROCEDURE PARSE ARG FileName RETURN(STREAM(Filename, 'C', 'QUERY EXISTS') > ''); /* ------------------------------------------------------------------------- */ LOWER: PROCEDURE Lower = 'abcdefghijklmnopqrstuvwxyz„”'; Upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZŽ™š'; PARSE ARG String RETURN(TRANSLATE(String, Lower, Upper)); /* ========================================================================= */ ReadIniValue: PROCEDURE PARSE ARG IniFile, IniAppname, IniKeyName IniValue = SysIni(IniFile, IniAppname, IniKeyName); IF (IniValue = 'ERROR:') THEN IniValue = ''; IF ((IniValue \= '') & (RIGHT(IniValue, 1) = "00"x)) THEN IniValue = LEFT( IniValue, LENGTH( IniValue) - 1); RETURN( IniValue); /* ------------------------------------------------------------------------- */ GetCalldir: PROCEDURE PARSE SOURCE . . CallName CallDir = FILESPEC('Drive', CallName)||FILESPEC('Path', CallName); RETURN(LEFT(CallDir, LENGTH(CallDir) - 1)); /* ------------------------------------------------------------------------- */ DirExist: PROCEDURE PARSE ARG Dirname IF (Dirname = '') THEN RETURN(0); /* use 'QUERY EXISTS' with root dirs */ IF (RIGHT(DirName, 2) = ':\') THEN RETURN(STREAM(Dirname, 'C', 'QUERY EXISTS') \= ''); /* query all others */ IF ((STREAM(Dirname, 'C', 'QUERY EXISTS') = '') &, (STREAM(Dirname, 'C', 'QUERY DATETIME') \= '')) THEN RETURN(1); ELSE RETURN(0); /* ========================================================================= */ GetFullName: PROCEDURE EXPOSE (GlobalVars) PARSE ARG UserId; IF (Fullname.UserId \= '') THEN RETURN Fullname.UserId; ELSE RETURN(UserId); /* ========================================================================= */ ReadLastChangeLogStamp: PROCEDURE EXPOSE (GlobalVars) PARSE ARG ChangeLogFile; LogStamp = ''; RangeTitle = 'log range: '; RangeTitleLen = LENGTH( RangeTitle); DO UNTIL (TRUE) /* Check file */ IF (\FileExist( ChangeLogFile)) THEN LEAVE; ThisLine = LINEIN( ChangeLogFile); IF (LEFT( ThisLine, 20) \= COPIES('-', 20)) THEN LEAVE; ThisLine = LINEIN( ChangeLogFile); IF (LEFT( ThisLine, RangeTitleLen) \= RangeTitle) THEN LEAVE; PARSE VAR ThisLine . 'to' LogStamp; END; rc = STREAM( ChangeLogFile, 'C', 'CLOSE'); RETURN( LogStamp); /* ========================================================================= */ ReadCvsLogEntries: PROCEDURE EXPOSE (GlobalVars) PARSE ARG Logfile, TmpFile; rc = ERROR.NO_ERROR; LineCount = 0; FileFooter = COPIES( '=', 77); RevisionHeader = COPIES( '-', 28); FilenameTitle = 'RCS file: '; FilenameTitleLen = LENGTH( FilenameTitle); fLogFound = FALSE; fReadRevisions = FALSE; fSkipFile = FALSE; DO UNTIL (TRUE) /* Check file */ IF (\FileExist( Logfile)) THEN DO SAY CmdName': error: cvs log output could not be found.'; rc = ERROR.FILE_NOT_FOUND; LEAVE; END; CALL CHAROUT, 'Reading log output ... '; /* read entries */ DO WHILE (LINES( LogFile) > 0) /* read line */ ThisLine = LINEIN( LogFile); IF (ThisLine = '') THEN ITERATE; fLogFound = TRUE; /* is it end of file section ? */ IF (ThisLine = FileFooter) THEN DO /* write out current info to tmp file */ IF ((\fSkipFile) & (fReadRevisions)) THEN rcx = LINEOUT( TmpFile, ''); fReadRevisions = FALSE; fSkipFile = FALSE; ITERATE; END; /* file to be skipped ? */ IF (fSkipFile) THEN ITERATE; /* get working filename and initialize revision list */ IF ( LEFT( ThisLine, FilenameTitleLen) = FilenameTitle)THEN DO Filename = DELSTR( ThisLine, 1, FilenameTitleLen); Filename = DELSTR( FileName, LENGTH( Filename) - 1); IF ( POS( '/CVSROOT/', Filename) > 0) THEN fSkipFile = TRUE; ITERATE; END; /* read revision entries */ IF (ThisLine = RevisionHeader) THEN DO IF (fReadRevisions) THEN rcx = LINEOUT( TmpFile, ''); fReadRevisions = TRUE; ThisRevision = LINEIN( LogFile); PARSE VAR ThisRevision 'revision' ThisRevision; ThisDate = LINEIN( LogFile); PARSE VAR ThisDate 'date:' ThisDate ThisTime';' 'author:' ThisAuthor';' rcx = CHAROUT( TmpFile, Filename STRIP(ThisRevision) STRIP( ThisDate) STRIP(ThisTime) STRIP( ThisAuthor)' '); ITERATE; END; /* read revision log text */ IF (fReadRevisions) THEN DO LineCount = LineCount + 1; rcx = CHAROUT( TmpFile, LineDelimiter''ThisLine); END; END; rcx = STREAM( TmpFile, 'C', 'CLOSE'); rcx = STREAM( LogFile, 'C', 'CLOSE'); SAY LineCount 'entries - Ok.'; END; IF (\fLogFound) THEN rc = ERROR.FILE_NOT_FOUND; RETURN( rc); /* ========================================================================= */ WriteChangeLog: PROCEDURE EXPOSE (GlobalVars) PARSE ARG ChangeLogfile, TmpFile, User, LogRange, CvsRoot; rc = ERROR.NO_ERROR; fRevisionsFound = FALSE; WrapCol = 70; Indent = ' '; NewFile = SysTempFileName( TmpDir'\cvsnew.???'); SortFile = SysTempFileName( TmpDir'\cvssort.???'); CopyFile = SysTempFileName( TmpDir'\cvscopy.???'); /* sort the temporary file */ 'gsort.bin +2 -4r +4 +0 <' TmpFile '>' SortFile; CALL CHAROUT, 'Generating changelog ... '; /* write new log entries: header */ rcx = SysFileDelete( NewFile); rcx = LINEOUT( NewFile, LogHeader); IF (LogRange \= '') THEN rcx = LINEOUT( NewFile, 'log range:' LogRange); rcx = LINEOUT( NewFile, 'generated by:' GetFullName( User)); rcx = LINEOUT( NewFile, ''); rcx = LINEOUT( NewFile, ''); /* preread one line */ ThisRevision = '' DO WHILE ((LINES(SortFile) > 0) & (ThisRevision = '')) ThisLine = LINEIN( SortFile); PARSE VAR ThisLine ThisFile ThisRevision ThisDate ThisTime ThisInfo ThisFile = DELSTR( ThisFile, 1, LENGTH( CvsRoot) + 1); END; DO WHILE (LINES(SortFile) > 0) /* reset file list */ FileList = ''; EndTime = ThisTime; NextRevision = ''; NetxtDate = ' '; /* preread following line */ DO WHILE ((LINES(SortFile) > 0) & (NextRevision = '')) NextLine = LINEIN( SortFile); PARSE VAR NextLine NextFile NextRevision NextDate NextTime NextInfo END; /* read all lines of same log info */ DO WHILE ((NextRevision \= '') & (ThisInfo = NextInfo)) FileList = FileList ThisFile; ThisFile = DELSTR( NextFile, 1, LENGTH( CvsRoot) + 1); /* preread as much as needed */ IF (LINES(SortFile) = 0) THEN LEAVE; NextLine = LINEIN( SortFile); StartTime = NextTime; PARSE VAR NextLine NextFile NextRevision NextDate NextTime NextInfo END; PARSE VAR ThisInfo ThisAuthor ThisLog; ThisInfo = NextInfo; ThisTime = NextTime; ThisAuthor = GetFullName( ThisAuthor); IF (WORDPOS( ThisFile, FileList) = 0) THEN FileList = ThisFile FileList; /* check out start and end time */ /* IF (StartTime = EndTime) THEN TimeRange = StartTime; ELSE TimeRange = StartTime '-' EndTime; */ TimeRange = StartTime; /* write out revision information */ fRevisionsFound = TRUE; rcx = LINEOUT( NewFile, '' NextDate TimeRange',' ThisAuthor); rcx = WriteFileList( NewFile, WrapCol, ' ', ' file(s):' STRIP(Filelist)); rcx = LINEOUT( NewFile, COPIES( ' - ', 23)); rcx = WriteLogComment( NewFile, WrapCol, ' ', ThisLog); rcx = LINEOUT( NewFile, ''); rcx = LINEOUT( NewFile, ''); END; rc = STREAM( SortFile, 'C', 'CLOSE'); rc = STREAM( NewFile, 'C', 'CLOSE'); IF (fRevisionsFound) THEN DO IF (FileExist( ChangeLogfile)) THEN DO /* append the old file to the new one */ 'copy' ChangeLogfile CopyFile Redirection; 'copy' NewFile '+' CopyFile ChangeLogfile Redirection; rcx = SysFileDelete( CopyFile); END; ELSE /* create the output file */ 'copy' NewFile ChangeLogfile Redirection; END; /* cleanup */ IF (fCleanup) THEN DO rcx = SysFileDelete( NewFile); rcx = SysFileDelete( SortFile); rcx = SysFileDelete( TmpFile); END; SAY 'Ok.'; IF (\fRevisionsFound) THEN SAY 'No revisions found in log range.' ChangeLogfile 'unchanged.'; RETURN(rc); /* ========================================================================= */ WriteFileList: PROCEDURE EXPOSE (GlobalVars) PARSE ARG File, WrapCol, Indent, Filelist; DO UNTIL (TRUE) /* output of one row only */ DO WHILE (LENGTH( FileList) >= WrapCol) /* check where to split the line */ SplitPos = LASTPOS( ' ', FileList, WrapCol); IF (SplitPos = 0) THEN SplitPos = POS( ' ', FileList, WrapCol); IF (SplitPos = 0) THEN LEAVE; /* split it and write the line */ ThisLine = LEFT( FileList, SplitPos - 1); FileList = Indent''STRIP(SUBSTR( FileList, SplitPos + 1)); rcx = LINEOUT( File, ThisLine); END; /* write only/last line */ IF (STRIP( FileList) \= '') THEN rcx = LINEOUT( File, FileList); END; RETURN(0); /* ========================================================================= */ WriteLogComment: PROCEDURE EXPOSE (GlobalVars) PARSE ARG File, WrapCol, Indent, Log; /* write out formatted change comment */ DO WHILE (Log \= '') DelimiterPos = POS( LineDelimiter, Log); IF (DelimiterPos > 0) THEN DO ThisPart = SUBSTR( Log, 1, DelimiterPos - 1); Log = SUBSTR( Log, DelimiterPos + 1); END; ELSE DO ThisPart = Log; Log = ''; END; IF (ThisPart \= '') THEN DO DO WHILE (LENGTH( ThisPart) >= WrapCol) /* check where to split the line */ SplitPos = LASTPOS( ' ', ThisPart, WrapCol); IF (SplitPos = 0) THEN SplitPos = POS( ' ', ThisPart, WrapCol); IF (SplitPos = 0) THEN LEAVE; /* split it and write the line */ ThisLine = LEFT( ThisPart, SplitPos - 1); ThisPart = STRIP(SUBSTR( ThisPart, SplitPos + 1)); rcx = LINEOUT( File, Indent Indent ThisLine); END; /* write only/last line */ IF (STRIP( ThisPart) \= '') THEN rcx = LINEOUT( File, Indent Indent ThisPart); END; END; RETURN(0);