2013-03-15 11:12 UTC+0100 Viktor Szakats (harbour syenar.net)
* /harbour/* -> /*
* moved whole Harbour source tree one level up to
avoid single 'harbour' top dir
This commit is contained in:
861
bin/3rdpatch.hb
Executable file
861
bin/3rdpatch.hb
Executable file
@@ -0,0 +1,861 @@
|
||||
#!/usr/bin/hbmk2
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* 3rdpatch - a tool to help update 3rd party components while keeping local fixes
|
||||
*
|
||||
* Copyright 2010, 2011 Tamas TEVESZ
|
||||
* See COPYING for licensing terms.
|
||||
*
|
||||
* 1. CONFIGURATION
|
||||
* ----------------
|
||||
*
|
||||
* For proper operation, several of the following external tools are required to
|
||||
* be present somewhere in your $PATH:
|
||||
*
|
||||
* - The GNU version of `patch', `diff' and `tar' (3rdpatch will figure it out
|
||||
* if you have them by the names of `gpatch', `gdiff' or `gtar')
|
||||
*
|
||||
* - curl, gzip, bzip2, xz and unzip (only the Info-ZIP version of unzip has
|
||||
* been tested)
|
||||
*
|
||||
* `curl' is unconditionally required for fetching source archives; the rest of the
|
||||
* tools are checked for on an on-demand basis.
|
||||
*
|
||||
* 3rdpatch requires several metadata (in the form of specially formatted lines)
|
||||
* in the component's Makefile (preferred) or .hbp file (if no Makefile is
|
||||
* present). Formatting rules are as follows:
|
||||
*
|
||||
* - The first character on the line is a hash mark (`#'), followed by any number
|
||||
* of white spaces.
|
||||
* - Next comes a keyword, followed by any number of white spaces.
|
||||
* - The keyword is followed by one or more arguments, separated by white spaces.
|
||||
* The number of arguments taken depends on the keyword itself.
|
||||
*
|
||||
* The keywords themselves are case sensitive (only upper case keywords are
|
||||
* recognized). The arguments are case sensitive as well.
|
||||
*
|
||||
* Currently recognized keywords and their arguments are as follows:
|
||||
*
|
||||
* ORIGIN
|
||||
* Takes one argument, the URL of component's home page. Not currently used,
|
||||
* but greatly helps locating resources regarding the component.
|
||||
* Example: for PCRE, it is `http://www.pcre.org/'.
|
||||
*
|
||||
* VER
|
||||
* Takes one argument, the version number of the component currently in the
|
||||
* Harbour tree. Not currently used, but greatly helps checking whether the
|
||||
* component needs an update.
|
||||
* Example: for PCRE, at the time of this writing, it is `8.02'.
|
||||
*
|
||||
* URL
|
||||
* Takes one argument, the URL to the archive to the currently installed
|
||||
* version of the component. Used by 3rdpatch.
|
||||
* Example: for PCRE, at the time of this writing, it is
|
||||
* `ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.02.zip'.
|
||||
* 3rdpatch can currently unpack only `tar.gz', `tar.bz2', `tgz', `tbz',
|
||||
* `tbz2', `tar.xz', `txz' and `zip' archives -- one of these must be chosen.
|
||||
*
|
||||
* 3rdpatch will also use the URL parameter to figure out what type of
|
||||
* file it is working with, so a URL containing this sort if information must
|
||||
* be picked. As an example, SourceForge-style distributed download URLs like
|
||||
* `http://sourceforge.net/projects/libpng/files/01-libpng-master/1.4.2/lpng142.zip/download'
|
||||
* are OK, but `http://example.com/download/latest' is not, even if latter
|
||||
* would ultimately result (perhaps by the server using Content-Disposition
|
||||
* or similar headers) in a file named `example-pkg-54.tar.gz'.
|
||||
*
|
||||
* DIFF
|
||||
* Takes one argument, the file name of the diff file containing local changes
|
||||
* needed by Harbour. In `rediff' mode, this parameter is optional; if not
|
||||
* specified, defaults to `$(component).dif'.
|
||||
* Example: for PCRE, it is `pcre.dif'.
|
||||
*
|
||||
* MAP
|
||||
* Takes one or two arguments, specifying the correspondence of the file names
|
||||
* between the original sources and the Harbour sources (which are reduced to
|
||||
* 8+3 format, in order to stay compatible with DOS).
|
||||
* If a particular file name is the same both in the upstream and the Harbour
|
||||
* trees, it is sufficient to specify it only once, but every file that needs
|
||||
* to be brought over to the Harbour tree must be specified.
|
||||
* The very first `MAP' occurrence is treated specially: it's argument is used
|
||||
* by 3rdpatch to locate the root of the extracted upstream source tree.
|
||||
* Examples:
|
||||
*
|
||||
* # MAP LICENCE
|
||||
*
|
||||
* The file named `LICENCE' needs to be brought over from the upstream tree
|
||||
* to the Harbour tree unchanged. In case of PCRE, `MAP LICENCE' being the
|
||||
* first `MAP' line also means that 3rdpatch will use the directory
|
||||
* containing this file as a base for all other files occurring later.
|
||||
* Accordingly, the first `MAP' entry must be flat even on the source side.
|
||||
*
|
||||
* # MAP config.h.generic config.h
|
||||
*
|
||||
* The file named `config.h.generic' in the upstream source tree needs to
|
||||
* be brought over to the Harbour tree by the name `config.h'.
|
||||
*
|
||||
* # MAP foo/bar.h
|
||||
*
|
||||
* If the upstream source tree is not flat, relative paths may also be
|
||||
* specified. The above means "bring `foo/bar.h' from upstream as `bar.h'
|
||||
* into the Harbour tree". Note that the Harbour component tree is always
|
||||
* flat, it is illegal to specify - for example - `MAP foo/bar.h zoink/baz.h'.
|
||||
*
|
||||
* # MAP foo/bar.h baz.h
|
||||
*
|
||||
* The upstream source file `foo/bar.h' needs to be brought over to the
|
||||
* Harbour tree as `baz.h'. All notes above about hierarchical and flat
|
||||
* trees strictly apply.
|
||||
*
|
||||
* For hierarchical source trees, the path separator must always be the UNIX
|
||||
* forward slash (`/'). DOS-style backslash separators are not recognized and
|
||||
* will produce undefined results.
|
||||
*
|
||||
* The `-validate' command line argument causes 3rdpatch to validate the
|
||||
* metadata without executing any actions that might otherwise be necessary.
|
||||
* It is recommended to use this after a component's metadata changes.
|
||||
*
|
||||
* 2. MODES OF OPERATION
|
||||
* ---------------------
|
||||
*
|
||||
* By default, 3rdpatch operates in `component version updating' mode - that is,
|
||||
* refreshing the component version to a newer upstream version. Let it be noted
|
||||
* that if the new version is very different from the currently in-tree version
|
||||
* (lots of new files, removed files, radically re-organized upstream source
|
||||
* tree, for example), 3rdpatch's utility will decrease steeply. In such cases
|
||||
* considering the full manual update of the component is advised.
|
||||
*
|
||||
* If 3rdpatch is called with the `-rediff' command line argument, it switches
|
||||
* to a `local diff refresh' mode. This mode is used to refresh the local diff
|
||||
* after Harbour-specific modifications have been made to the component's
|
||||
* source. In order to help with the initial diff creation, 3rdpatch will proceed
|
||||
* even if no `DIFF' is specified amongst the metadata, and defaults to
|
||||
* creating a diff named `$(component).dif').
|
||||
*
|
||||
* If no differences between the original and the Harbour trees were found,
|
||||
* a possibly pre-existing diff file is removed. Following this change up
|
||||
* in the component's Makefile (or .hbp file) is left for the operator -- 3rdpatch
|
||||
* will communicate if there is a likely need to perform this action.
|
||||
*
|
||||
* It is strongly advised not to try to mix the two modes. If there are any
|
||||
* pending local modifications, a rediff should be done before a component
|
||||
* version update is performed.
|
||||
*
|
||||
* 3. TYPICAL WORKFLOW
|
||||
* -------------------
|
||||
*
|
||||
* Once it has been determined that a particular component needs an update, the URL
|
||||
* argument has to be modified to point to the new source tree archive. VER should
|
||||
* also be updated. While residing in the component's directory, 3rdpatch needs
|
||||
* to be run. The rest is mostly automatic - 3rdpatch retrieves, unpacks and
|
||||
* otherwise prepares the updated source tree, applies any local modifications,
|
||||
* and copies any changes back to the Harbour tree (the current working directory).
|
||||
* After some inspection and a test, it is ready to be committed.
|
||||
*
|
||||
* In rediff mode, care must be taken for the URL keyword to contain a reference
|
||||
* to the version that is in the current Harbour tree (that basically means `do not
|
||||
* touch anything', assuming correct information in the first place). After 3rdpatch
|
||||
* is finished rediffing, the new `local changes' file (see `DIFF') may be inspected,
|
||||
* and is ready to be committed.
|
||||
*
|
||||
* If errors are encountered during rediff, the contents of the temporary directory
|
||||
* may be used as a starting basis for manual re-diffing.
|
||||
*
|
||||
* 4. TROUBLESHOOTING
|
||||
* ------------------
|
||||
*
|
||||
* Several things can go wrong, and 3rdpatch tries hard handle them as gracefully as
|
||||
* possible. First and foremost, in case of even the slightest sign of something
|
||||
* not happening as intended, 3rdpatch will not modify the Harbour tree at all.
|
||||
* Everything is happening inside a temporary directory, which is not erased when
|
||||
* 3rdpatch exits (not even when it exits normally), and where certain log files are
|
||||
* created. These log files may contain information to help debugging in case of
|
||||
* an (unhandled) error.
|
||||
*
|
||||
* The organization of the temporary directory is as follows:
|
||||
*
|
||||
* $(component) These directories are the extracted and modified versions
|
||||
* $(component).orig of the upstream source tree. The `.orig' tree consists of
|
||||
* only renamed (and renames followed up in the files),
|
||||
* whereas the $(component) tree will have the local
|
||||
* modifications (see the `DIFF' keyword) applied. These two
|
||||
* directories are used for re-creating the local changes.
|
||||
*
|
||||
* root The new upstream source is unpacked in this directory.
|
||||
*
|
||||
* fetch.log The output `curl' produced while fetching the source
|
||||
* archive.
|
||||
*
|
||||
* extract.log The output the extractor (gzip, bzip2, xz) produced
|
||||
* while uncompressing the archive.
|
||||
*
|
||||
* archive.log The output the archiver (tar, unzip) produced while
|
||||
* unpacking the archive.
|
||||
*
|
||||
* patch.log The output `patch' produced while applying the local
|
||||
* changes to $(component).
|
||||
*
|
||||
* diff.log The standard error of `diff' produced while re-creating
|
||||
* the local changes (the standard output is the diff itself
|
||||
* and is placed in the local changes file, see `DIFF').
|
||||
*
|
||||
* some archive file The new source tree archive.
|
||||
*
|
||||
* In all error cases 3rdpatch will provide a meaningful error message. Armed with
|
||||
* that and the information here, troubleshooting should not be much of a problem.
|
||||
*
|
||||
* 4. BUGS
|
||||
* -------
|
||||
*
|
||||
* None known. More testing on non-UNIX systems is desired.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma -w3
|
||||
#pragma -km+
|
||||
#pragma -ko+
|
||||
|
||||
#include "directry.ch"
|
||||
|
||||
#if defined( _TRACE )
|
||||
#define TRACE( str ) OutStd( "T: " + str + hb_eol() )
|
||||
#else
|
||||
#define TRACE( str )
|
||||
#endif
|
||||
|
||||
#define ONEARG_KW 2 /* one-arg line keyword */
|
||||
#define ONEARG_ARG 3 /* one-arg line argument */
|
||||
#define TWOARG_KW 2 /* two-arg line keyword */
|
||||
#define TWOARG_ARG1 3 /* two-arg line first argument */
|
||||
#define TWOARG_ARG2 4 /* two-arg line second argument */
|
||||
|
||||
#define FN_ORIG 1 /* original file name in maps */
|
||||
#define FN_HB 2 /* hb file name in maps */
|
||||
|
||||
STATIC s_aChangeMap := {} /* from-to file name map */
|
||||
STATIC s_cTempDir := NIL
|
||||
STATIC s_nErrors := 0 /* error indicator */
|
||||
STATIC s_cSourceRoot := NIL /* top directory of the newly-unpacked source tree */
|
||||
|
||||
STATIC s_aTools := { ;
|
||||
"patch" => NIL, ;
|
||||
"diff" => NIL, ;
|
||||
"curl" => NIL, ;
|
||||
"tar" => NIL, ;
|
||||
"gzip" => NIL, ;
|
||||
"bzip2" => NIL, ;
|
||||
"xz" => NIL, ;
|
||||
"unzip" => NIL }
|
||||
|
||||
PROCEDURE Main( ... )
|
||||
|
||||
LOCAL cFileName
|
||||
LOCAL cFile /* memorized input make file */
|
||||
LOCAL aDir
|
||||
LOCAL aRegexMatch /* regex match results */
|
||||
LOCAL cMemoLine /* MemoLine */
|
||||
LOCAL nMemoLine /* Line number */
|
||||
LOCAL cDiffFile /* Local modifications */
|
||||
LOCAL cCWD
|
||||
LOCAL cThisComponent /* component being processed */
|
||||
LOCAL aOneMap /* one pair from s_aChangeMap */
|
||||
LOCAL cCommand /* patch/diff commands */
|
||||
LOCAL nRunResult /* patch/diff exit vals */
|
||||
LOCAL cDiffText /* diff will return the new diff in this */
|
||||
LOCAL nDiffFD /* for writing newly created diff file */
|
||||
LOCAL cArchiveURL /* URL for the component */
|
||||
LOCAL cTopIndicator /* file signifying the top of the component's source tree */
|
||||
LOCAL cStdOut /* stdout and stderr for various externally-run apps */
|
||||
LOCAL cStdErr
|
||||
LOCAL lRediff := .F. /* whether or not operating as rediff */
|
||||
LOCAL lValidateOnly := .F. /* syntactic metadata validation only */
|
||||
LOCAL cArg
|
||||
LOCAL cRoot := NIL
|
||||
|
||||
LOCAL hRegexTake1Line := hb_regexComp( "^#[[:blank:]]*(ORIGIN|VER|URL|DIFF)[[:blank:]]+(.+?)[[:blank:]]*$" )
|
||||
LOCAL hRegexTake2Line := hb_regexComp( "^#[[:blank:]]*(MAP)[[:blank:]]+(.+?)[[:blank:]]+(.+?)[[:blank:]]*$" )
|
||||
|
||||
FOR EACH cArg IN hb_AParams()
|
||||
SWITCH cArg
|
||||
CASE "-rediff"
|
||||
lRediff := .T.
|
||||
EXIT
|
||||
CASE "-validate"
|
||||
lValidateOnly := .T.
|
||||
EXIT
|
||||
CASE "-h"
|
||||
CASE "-help"
|
||||
CASE "--help"
|
||||
CASE "/?"
|
||||
Usage( 0 )
|
||||
OTHERWISE
|
||||
Usage( 1 )
|
||||
ENDSWITCH
|
||||
NEXT
|
||||
|
||||
IF ! hb_FileExists( cFileName := "Makefile" )
|
||||
IF Empty( aDir := Directory( "*.hbp" ) )
|
||||
OutStd( "No `Makefile' or '*.hbp' file in the current directory." + hb_eol() )
|
||||
ErrorLevel( 1 )
|
||||
QUIT
|
||||
ELSE
|
||||
ASort( aDir,,, {| tmp, tmp1 | tmp[ F_NAME ] < tmp1[ F_NAME ] } )
|
||||
cFileName := aDir[ 1 ][ F_NAME ]
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
SetupTools()
|
||||
|
||||
cFile := MemoRead( cFileName )
|
||||
cDiffFile := NIL /* default to `no local diff' */
|
||||
|
||||
nMemoLine := 0
|
||||
|
||||
FOR EACH cMemoLine IN hb_ATokens( StrTran( cFile, Chr( 13 ) ), Chr( 10 ) )
|
||||
|
||||
cMemoLine := AllTrim( cMemoLine )
|
||||
nMemoLine++
|
||||
|
||||
IF ! Empty( aRegexMatch := hb_regex( hRegexTake1Line, cMemoLine ) )
|
||||
/* Process one-arg keywords */
|
||||
IF aRegexMatch[ ONEARG_KW ] == "DIFF"
|
||||
cDiffFile := iif( Empty( AllTrim( aRegexMatch[ ONEARG_ARG ] ) ), NIL, ;
|
||||
AllTrim( aRegexMatch[ ONEARG_ARG ] ) )
|
||||
ELSEIF aRegexMatch[ ONEARG_KW ] == "URL"
|
||||
cArchiveURL := AllTrim( aRegexMatch[ ONEARG_ARG ] )
|
||||
ENDIF
|
||||
|
||||
ELSEIF ! Empty( aRegexMatch := hb_regex( hRegexTake2Line, cMemoLine ) )
|
||||
/* Process two-arg keywords */
|
||||
IF aRegexMatch[ TWOARG_KW ] == "MAP"
|
||||
/* Do not allow implicit destination with non-flat source spec */
|
||||
IF Empty( aRegexMatch[ TWOARG_ARG1 ] ) .AND. "/" $ aRegexMatch[ TWOARG_ARG2 ]
|
||||
OutStd( hb_StrFormat( "E: Non-flat source spec with implicit " + ;
|
||||
"destination, offending line %d:%s:", nMemoLine, hb_eol() ) )
|
||||
OutStd( aRegexMatch[ 1 ] + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
/* Do not allow tree spec in the destination ever */
|
||||
IF "/" $ aRegexMatch[ TWOARG_ARG2 ]
|
||||
OutStd( hb_StrFormat( "E: Non-flat destination, offending line %d:%s", ;
|
||||
nMemoLine, hb_eol() ) )
|
||||
OutStd( aRegexMatch[ 1 ] + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
/* If the source argument indicates the source tree is not flat, convert
|
||||
* path separator to native. The HB tree is always flattened. */
|
||||
IF "/" $ aRegexMatch[ TWOARG_ARG1 ]
|
||||
aRegexMatch[ TWOARG_ARG1 ] := StrTran( aRegexMatch[ TWOARG_ARG1 ], "/", hb_ps() )
|
||||
ENDIF
|
||||
/* The destination argument must fit in the 8+3 scheme */
|
||||
IF Len( hb_FNameName( aRegexMatch[ TWOARG_ARG2 ] ) ) > 8 .OR. ;
|
||||
Len( hb_FNameExt( aRegexMatch[ TWOARG_ARG2 ] ) ) > 4
|
||||
OutStd( hb_StrFormat( "E: Destination does not fit 8+3, offending " + ;
|
||||
"line %d:%s", nMemoLine, hb_eol() ) )
|
||||
OutStd( aRegexMatch[ 1 ] + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
/* In case the priginal and the HB file names are identical, the
|
||||
* second argument to `MAP' is optional. Due to the way the regex is
|
||||
* constructed, in this case the last backref will contain the only
|
||||
* file name, so shuffle arguments around accordingly
|
||||
*/
|
||||
AAdd( s_aChangeMap, { ;
|
||||
iif( Empty( aRegexMatch[ TWOARG_ARG1 ] ), ;
|
||||
aRegexMatch[ TWOARG_ARG2 ], ;
|
||||
aRegexMatch[ TWOARG_ARG1 ] ), aRegexMatch[ TWOARG_ARG2 ] ;
|
||||
} )
|
||||
/* If this is the first MAP entry, treat the original part as the
|
||||
* source tree root indicator */
|
||||
IF Len( s_aChangeMap ) == 1
|
||||
cTopIndicator := s_aChangeMap[ 1 ][ FN_ORIG ]
|
||||
IF "/" $ cTopIndicator
|
||||
OutStd( hb_StrFormat( "E: First `MAP' entry is not flat, offending " + ;
|
||||
"line %d:%s", nMemoLine, hb_eol() ) )
|
||||
OutStd( aRegexMatch[ 1 ] + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
IF lValidateOnly
|
||||
OutStd( "Metadata syntax is OK." + hb_eol() )
|
||||
QUIT
|
||||
ENDIF
|
||||
|
||||
IF Empty( s_aChangeMap ) .AND. cDiffFile == NIL
|
||||
OutStd( "No file name changes and no local diff, nothing to do." + hb_eol() )
|
||||
QUIT
|
||||
ENDIF
|
||||
|
||||
IF ! lRediff .AND. cDiffFile != NIL .AND. ! hb_FileExists( cDiffFile )
|
||||
OutStd( "E: `" + cDiffFile + "' does not exist" + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
|
||||
cCWD := hb_CurDrive() + hb_osDriveSeparator() + hb_ps() + CurDir()
|
||||
|
||||
#if defined( _CURDIR )
|
||||
cRoot := cCWD + hb_ps()
|
||||
#endif
|
||||
|
||||
FClose( hb_FTempCreateEx( @s_cTempDir, cRoot, hb_FNameName( hb_ProgName() ) + "_" ) )
|
||||
FErase( s_cTempDir )
|
||||
hb_DirCreate( s_cTempDir )
|
||||
|
||||
cThisComponent := hb_FNameName( cCWD )
|
||||
|
||||
hb_DirCreate( CombinePath( s_cTempDir, cThisComponent ) )
|
||||
hb_DirCreate( CombinePath( s_cTempDir, cThisComponent + ".orig" ) )
|
||||
hb_DirCreate( CombinePath( s_cTempDir, "root" ) )
|
||||
|
||||
IF lRediff .AND. cDiffFile == NIL
|
||||
OutStd( "Requested rediff mode with no existing local diff, attempting to create one." + hb_eol() )
|
||||
cDiffFile := cThisComponent + ".dif"
|
||||
ENDIF
|
||||
|
||||
IF ! FetchAndExtract( cArchiveURL )
|
||||
OutStd( "E: Fetching or extracting the source archive failed." + hb_eol() )
|
||||
OutStd( " Inspect `" + s_cTempDir + "' for further clues." + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
|
||||
s_cSourceRoot := WalkAndFind( CombinePath( s_cTempDir, "root" ), cTopIndicator )
|
||||
IF s_cSourceRoot == NIL
|
||||
OutStd( "E: Unable to find the new tree's root" + hb_eol() )
|
||||
OutStd( " Inspect `" + s_cTempDir + "'" + hb_eol() )
|
||||
ErrorLevel( 2 )
|
||||
QUIT
|
||||
ENDIF
|
||||
|
||||
/*
|
||||
* Create two copies of the relevant portions of the source archive.
|
||||
* The pristine tree is for reference, used as the left component of the diff
|
||||
* Our tree will have the local diff applied, and used as the right component of the diff
|
||||
*/
|
||||
FOR EACH aOneMap IN s_aChangeMap
|
||||
IF ! hb_FileExists( CombinePath( s_cSourceRoot, aOneMap[ FN_ORIG ] ) )
|
||||
OutStd( "W: `" + aOneMap[ FN_ORIG ] + "' does not exist in the source tree" + hb_eol() )
|
||||
OutStd( " I will do what i can, but you'd better check the results manually." + hb_eol() )
|
||||
s_nErrors++
|
||||
ELSE
|
||||
/* Create the `pristine tree' */
|
||||
hb_FCopy( ;
|
||||
CombinePath( s_cSourceRoot, aOneMap[ FN_ORIG ] ), ;
|
||||
CombinePath( s_cTempDir, cThisComponent + ".orig", aOneMap[ FN_HB ] ) )
|
||||
|
||||
/* Munch the file, applying the appropriate xforms */
|
||||
hb_FileTran( CombinePath( s_cTempDir, cThisComponent + ".orig", aOneMap[ FN_HB ] ) )
|
||||
|
||||
/* If operating in `rediff' mode, copy the current Harbour component tree;
|
||||
* otherwise, duplicate the pristine tree */
|
||||
|
||||
IF lRediff
|
||||
hb_FCopy( ;
|
||||
aOneMap[ FN_HB ], ;
|
||||
CombinePath( s_cTempDir, cThisComponent, aOneMap[ FN_HB ] ) )
|
||||
|
||||
ELSE
|
||||
/* Copy it to `our tree' */
|
||||
hb_FCopy( ;
|
||||
CombinePath( s_cTempDir, cThisComponent + ".orig", aOneMap[ FN_HB ] ), ;
|
||||
CombinePath( s_cTempDir, cThisComponent, aOneMap[ FN_HB ] ) )
|
||||
ENDIF
|
||||
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
IF cDiffFile != NIL
|
||||
|
||||
IF ! lRediff /* If we have a local diff, and are not to re-create it, apply */
|
||||
cCommand := hb_StrFormat( "%s --no-backup-if-mismatch -d %s -p 1 -i %s", ;
|
||||
s_aTools[ "patch" ], ;
|
||||
CombinePath( s_cTempDir, cThisComponent ), ;
|
||||
CombinePath( cCWD, cDiffFile ) )
|
||||
TRACE( "Running " + cCommand )
|
||||
nRunResult := hb_processRun( cCommand, , @cStdOut, @cStdErr, .F. )
|
||||
SaveLog( "patch", cStdOut, cStdErr )
|
||||
IF nRunResult != 0
|
||||
OutStd( "W: Unexpected events happened during patching, inspect " + s_cTempDir + hb_eol() )
|
||||
s_nErrors++
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
/* Re-create the diff */
|
||||
cCommand := hb_StrFormat( "%s -urN %s %s", ;
|
||||
s_aTools[ "diff" ], cThisComponent + ".orig", cThisComponent )
|
||||
|
||||
DirChange( s_cTempDir )
|
||||
TRACE( "Running " + cCommand )
|
||||
hb_processRun( cCommand, , @cDiffText, @cStdErr, .F. )
|
||||
DirChange( cCWD )
|
||||
|
||||
SaveLog( "diff", NIL, cStdErr )
|
||||
|
||||
IF Len( cDiffText ) > 0
|
||||
nDiffFD := FCreate( cDiffFile )
|
||||
FWrite( nDiffFD, cDiffText )
|
||||
FClose( nDiffFD )
|
||||
OutStd( "Local changes saved to `" + cDiffFile + "'; you may need to adjust `DIFF'." + hb_eol() )
|
||||
ELSE
|
||||
OutStd( "No local changes; you may need to adjust `DIFF'." + hb_eol() )
|
||||
IF hb_FileExists( cDiffFile )
|
||||
FErase( cDiffFile )
|
||||
OutStd( "Removed existing `" + cDiffFile + "'." + hb_eol() )
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
ENDIF
|
||||
|
||||
/* Only copy files back to the live tree if no errors were encountered */
|
||||
IF s_nErrors == 0
|
||||
IF ! lRediff
|
||||
/* Only copy the complete new tree back if not in Rediff mode */
|
||||
FOR EACH aOneMap IN s_aChangeMap
|
||||
hb_FCopy( CombinePath( s_cTempDir, cThisComponent, aOneMap[ FN_HB ] ), aOneMap[ FN_HB ] )
|
||||
NEXT
|
||||
ENDIF
|
||||
|
||||
IF cDiffFile != NIL
|
||||
/* Copy the diff back to the live tree */
|
||||
hb_FCopy( CombinePath( s_cTempDir, cDiffFile ), cDiffFile )
|
||||
ENDIF
|
||||
|
||||
ELSE
|
||||
OutStd( "Errors were encountered, no changes are made to your Harbour tree." + hb_eol() )
|
||||
OutStd( "Inspect " + s_cTempDir + " for further clues." + hb_eol() )
|
||||
ENDIF
|
||||
|
||||
IF ! lRediff
|
||||
OutStd( "Don't forget to update `" + cFileName + "' with the new version and URL information." + hb_eol() )
|
||||
ENDIF
|
||||
OutStd( "The temporary directory `" + s_cTempDir + "' has not been removed." + hb_eol() )
|
||||
|
||||
RETURN
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
STATIC PROCEDURE SetupTools()
|
||||
|
||||
#if defined( __PLATFORM__UNIX )
|
||||
LOCAL cExeExt := ""
|
||||
#else
|
||||
LOCAL cExeExt := ".exe"
|
||||
#endif
|
||||
LOCAL cPathComp
|
||||
LOCAL cTool
|
||||
|
||||
/* Look for g$tool first, only attempt raw name if it isn't found
|
||||
* Helps non-GNU userland systems with GNU tools installed.
|
||||
* Only several of the tools are known to have GNU variants. */
|
||||
|
||||
FOR EACH cPathComp IN hb_ATokens( GetEnv( "PATH" ), hb_osPathListSeparator() )
|
||||
FOR EACH cTool IN hb_HKeys( s_aTools )
|
||||
IF cTool $ "patch|diff|tar" .AND. hb_FileExists( CombinePath( cPathComp, "g" + cTool ) + cExeExt )
|
||||
s_aTools[ cTool ] := CombinePath( cPathComp, "g" + cTool )
|
||||
ENDIF
|
||||
NEXT
|
||||
NEXT
|
||||
|
||||
FOR EACH cPathComp IN hb_ATokens( GetEnv( "PATH" ), hb_osPathListSeparator() )
|
||||
FOR EACH cTool IN hb_HKeys( s_aTools )
|
||||
IF s_aTools[ cTool ] == NIL .AND. hb_FileExists( CombinePath( cPathComp, cTool ) + cExeExt )
|
||||
s_aTools[ cTool ] := CombinePath( cPathComp, cTool )
|
||||
ENDIF
|
||||
NEXT
|
||||
NEXT
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION CombinePath( ... )
|
||||
|
||||
LOCAL aArguments := hb_AParams()
|
||||
LOCAL cRetVal := ""
|
||||
LOCAL nI
|
||||
|
||||
IF Len( aArguments ) == 2
|
||||
cRetVal := aArguments[ 1 ] + hb_ps() + aArguments[ 2 ]
|
||||
ELSE
|
||||
cRetVal := aArguments[ 1 ] + hb_ps()
|
||||
FOR nI := 2 TO Len( aArguments ) - 1
|
||||
cRetVal += aArguments[ nI ] + hb_ps()
|
||||
NEXT
|
||||
cRetVal += aArguments[ Len( aArguments ) ]
|
||||
ENDIF
|
||||
|
||||
RETURN cRetVal
|
||||
|
||||
STATIC FUNCTION WalkAndFind( cTop, cLookFor )
|
||||
|
||||
LOCAL aDir
|
||||
LOCAL aDirEntry
|
||||
LOCAL cRetVal := NIL
|
||||
|
||||
cTop += iif( Right( cTop, 1 ) $ "/\", "", hb_ps() )
|
||||
aDir := Directory( cTop + hb_osFileMask(), "D" )
|
||||
|
||||
ASort( aDir,,, {| aLeft | !( "D" $ aLeft[ F_ATTR ] ) } ) /* Files first */
|
||||
|
||||
FOR EACH aDirEntry IN aDir
|
||||
IF !( "D" $ aDirEntry[ F_ATTR ] )
|
||||
IF aDirEntry[ F_NAME ] == cLookFor
|
||||
cRetVal := cTop
|
||||
EXIT
|
||||
ENDIF
|
||||
ELSEIF !( aDirEntry[ F_NAME ] == "." ) .AND. ;
|
||||
!( aDirEntry[ F_NAME ] == ".." )
|
||||
cRetVal := WalkAndFind( cTop + aDirEntry[ F_NAME ], cLookFor )
|
||||
IF ! Empty( cRetVal )
|
||||
EXIT
|
||||
ENDIF
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
RETURN cRetVal
|
||||
|
||||
STATIC FUNCTION FetchAndExtract( cArchiveURL )
|
||||
|
||||
LOCAL cCommand
|
||||
LOCAL cExtractor := NIL
|
||||
LOCAL cExtractorArgs := NIL
|
||||
LOCAL cExtractedFileName := NIL
|
||||
LOCAL cArchiver := NIL
|
||||
LOCAL cArchiverArgs := NIL
|
||||
LOCAL nResult
|
||||
LOCAL cStdOut
|
||||
LOCAL cStdErr
|
||||
LOCAL cPattern
|
||||
LOCAL cMatchedPattern
|
||||
LOCAL cFileName
|
||||
LOCAL cFrag
|
||||
LOCAL cCWD
|
||||
|
||||
/* Any given package is surely available in at least one of these formats,
|
||||
* pick one of these, refrain from the more exotic ones. */
|
||||
|
||||
LOCAL aActionMap := { ;
|
||||
".tar.gz|.tgz" => { ;
|
||||
"Extractor" => "gzip", ;
|
||||
"ExtractorArgs" => "-d", ;
|
||||
"ExtractedFile" => ".tar", ;
|
||||
"Archiver" => "tar", ;
|
||||
"ArchiverArgs" => "--force-local -xvf" ;
|
||||
}, ;
|
||||
".tar.bz2|.tbz|.tbz2" => { ;
|
||||
"Extractor" => "bzip2", ;
|
||||
"ExtractorArgs" => "-d", ;
|
||||
"ExtractedFile" => ".tar", ;
|
||||
"Archiver" => "tar", ;
|
||||
"ArchiverArgs" => "--force-local -xvf" ;
|
||||
}, ;
|
||||
".tar.xz|.txz" => { ;
|
||||
"Extractor" => "xz", ;
|
||||
"ExtractorArgs" => "-d", ;
|
||||
"ExtractedFile" => ".tar", ;
|
||||
"Archiver" => "tar", ;
|
||||
"ArchiverArgs" => "--force-local -xvf" ;
|
||||
}, ;
|
||||
".zip" => { ;
|
||||
"Extractor" => NIL, ;
|
||||
"ExtractorArgs" => NIL, ;
|
||||
"ExtractedFile" => NIL, ;
|
||||
"Archiver" => "unzip", ;
|
||||
"ArchiverArgs" => "" ;
|
||||
} ;
|
||||
}
|
||||
|
||||
IF Empty( cArchiveURL )
|
||||
OutStd( "E: URL missing" + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
|
||||
cFileName := URL_GetFileName( cArchiveURL )
|
||||
|
||||
FOR EACH cPattern IN hb_HKeys( aActionMap )
|
||||
FOR EACH cFrag IN hb_ATokens( cPattern, "|" )
|
||||
IF At( cFrag, cFileName ) != 0
|
||||
cMatchedPattern := cFrag
|
||||
cExtractor := aActionMap[ cPattern ][ "Extractor" ]
|
||||
cExtractorArgs := aActionMap[ cPattern ][ "ExtractorArgs" ]
|
||||
cExtractedFileName := iif( aActionMap[ cPattern ][ "ExtractedFile" ] == NIL, ;
|
||||
NIL, ;
|
||||
Left( cFileName, Len( cFileName ) - ;
|
||||
Len( cMatchedPattern ) ) + ;
|
||||
aActionMap[ cPattern ][ "ExtractedFile" ] )
|
||||
cArchiver := aActionMap[ cPattern ][ "Archiver" ]
|
||||
cArchiverArgs := aActionMap[ cPattern ][ "ArchiverArgs" ]
|
||||
EXIT
|
||||
ENDIF
|
||||
NEXT
|
||||
NEXT
|
||||
|
||||
IF cArchiver == NIL
|
||||
OutStd( "E: Can not find archiver for `" + ;
|
||||
hb_FNameNameExt( cArchiveURL ) + "'" + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
|
||||
/* Fetch */
|
||||
IF s_aTools[ "curl" ] == NIL
|
||||
OutStd( "E: Required `curl' was not found" + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
cCommand := hb_StrFormat( "%s -L -# -o %s %s", s_aTools[ "curl" ], ;
|
||||
CombinePath( s_cTempDir, cFileName ), FNameEscape( cArchiveURL ) )
|
||||
TRACE( "Running " + cCommand )
|
||||
nResult := hb_processRun( cCommand, , , @cStdErr, .F. )
|
||||
SaveLog( "fetch", cStdOut, cStdErr )
|
||||
IF nResult != 0
|
||||
OutStd( "E: Error fetching " + cArchiveURL + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
|
||||
/* Extract */
|
||||
IF cExtractor != NIL /* May not need extraction */
|
||||
IF s_aTools[ cExtractor ] == NIL
|
||||
OutStd( "E: Required `" + cExtractor + "' was not found" + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
cCommand := hb_StrFormat( "%s " + cExtractorArgs + " %s", ;
|
||||
cExtractor, CombinePath( s_cTempDir, cFileName ) )
|
||||
TRACE( "Running " + cCommand )
|
||||
nResult := hb_processRun( cCommand, , @cStdOut, @cStdErr, .F. )
|
||||
SaveLog( "extract", cStdOut, cStdErr )
|
||||
IF nResult != 0
|
||||
OutStd( "E: Error extracting " + cFileName + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
ELSE
|
||||
cExtractedFileName := cFileName
|
||||
ENDIF
|
||||
|
||||
/* Unarchive */
|
||||
IF s_aTools[ cArchiver ] == NIL
|
||||
OutStd( "E: Required `" + cArchiver + "' was not found" + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
cCommand := hb_StrFormat( "%s " + cArchiverArgs + " %s", ;
|
||||
cArchiver, CombinePath( s_cTempDir, cExtractedFileName ) )
|
||||
TRACE( "Running " + cCommand )
|
||||
cCWD := hb_CurDrive() + hb_osDriveSeparator() + hb_ps() + CurDir()
|
||||
DirChange( CombinePath( s_cTempDir, "root" ) )
|
||||
nResult := hb_processRun( cCommand, , @cStdOut, @cStdErr, .F. )
|
||||
DirChange( cCWD )
|
||||
SaveLog( "archive", cStdOut, cStdErr )
|
||||
IF nResult != 0
|
||||
OutStd( "E: Error unarchiving " + cFileName + hb_eol() )
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
|
||||
RETURN .T.
|
||||
|
||||
STATIC PROCEDURE SaveLog( cFNTemplate, cStdOut, cStdErr )
|
||||
|
||||
LOCAL nLogFD
|
||||
|
||||
nLogFD := FCreate( CombinePath( s_cTempDir, cFNTemplate + ".log" ) )
|
||||
|
||||
IF cStdOut != NIL
|
||||
FWrite( nLogFd, "stdout:" + hb_eol() )
|
||||
FWrite( nLogFD, cStdOut )
|
||||
ENDIF
|
||||
IF cStdErr != NIL
|
||||
FWrite( nLogFd, "stderr:" + hb_eol() )
|
||||
FWrite( nLogFD, cStdErr )
|
||||
ENDIF
|
||||
FClose( nLogFD )
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC PROCEDURE Usage( nExitVal )
|
||||
|
||||
OutStd( "Usage: " + hb_FNameNameExt( hb_ProgName() ) + " [-h|-help|-rediff]" + hb_eol() )
|
||||
OutStd( " Documentation is provided in the source code." + hb_eol() )
|
||||
ErrorLevel( nExitVal )
|
||||
QUIT
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION URL_GetFileName( cURL )
|
||||
|
||||
LOCAL aComponents
|
||||
LOCAL cName
|
||||
LOCAL nIdx
|
||||
|
||||
aComponents := hb_ATokens( cURL, "/" )
|
||||
nIdx := Len( aComponents )
|
||||
|
||||
IF nIdx < 4 /* now what */
|
||||
RETURN ""
|
||||
ENDIF
|
||||
|
||||
cName := aComponents[ nIdx ]
|
||||
cName := iif( "?" $ cName, Left( cName, At( "?", cName ) - 1 ), cName ) /* strip params */
|
||||
|
||||
DO WHILE !( "." $ cName )
|
||||
cName := aComponents[ --nIdx ]
|
||||
IF nIdx < 4 /* don't drain all components */
|
||||
RETURN ""
|
||||
ENDIF
|
||||
ENDDO
|
||||
|
||||
RETURN cName
|
||||
|
||||
STATIC FUNCTION hb_FileTran( cFileName )
|
||||
|
||||
LOCAL cFileContent
|
||||
LOCAL cTransformedContent
|
||||
LOCAL aChange
|
||||
LOCAL cChangeFrom
|
||||
LOCAL cChangeTo
|
||||
|
||||
cFileContent := hb_MemoRead( cFileName )
|
||||
|
||||
/* CRLF -> LF */
|
||||
cTransformedContent := StrTran( cFileContent, Chr( 13 ) + Chr( 10 ), Chr( 10 ) )
|
||||
|
||||
/* LF -> native */
|
||||
cTransformedContent := StrTran( cTransformedContent, Chr( 10 ), hb_eol() )
|
||||
|
||||
FOR EACH aChange IN s_aChangeMap
|
||||
|
||||
/* This is a shot in the dark. Haru works with this transform,
|
||||
* but other components may very well need different handling. */
|
||||
cChangeFrom := hb_FNameNameExt( aChange[ 1 ] )
|
||||
cChangeTo := aChange[ 2 ]
|
||||
|
||||
/* Local-style includes */
|
||||
cTransformedContent := StrTran( cTransformedContent, ;
|
||||
'"' + cChangeFrom + '"', ;
|
||||
'"' + cChangeTo + '"' )
|
||||
|
||||
/* System-style include */
|
||||
cTransformedContent := StrTran( cTransformedContent, ;
|
||||
"<" + cChangeFrom + ">", ;
|
||||
"<" + cChangeTo + ">" )
|
||||
|
||||
NEXT
|
||||
|
||||
RETURN hb_MemoWrit( cFileName, cTransformedContent )
|
||||
|
||||
STATIC FUNCTION FNameEscape( cFileName )
|
||||
|
||||
#if defined( __PLATFORM__UNIX )
|
||||
cFileName := '"' + cFileName + '"'
|
||||
#endif
|
||||
|
||||
RETURN cFileName
|
||||
|
||||
/*
|
||||
* vim: ts=3 expandtab ft=clipper
|
||||
*/
|
||||
233
bin/commit.hb
Normal file
233
bin/commit.hb
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Harbour Project source code:
|
||||
* Commit preparer
|
||||
*
|
||||
* Copyright 2012 Viktor Szakats (harbour syenar.net)
|
||||
* www - http://harbour-project.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
|
||||
* their web site at http://www.gnu.org/).
|
||||
*
|
||||
*/
|
||||
|
||||
#define _CONFIGFIL_ ".hbcommit"
|
||||
#define _CONFIGENV_ "HBCOMMIT_USER"
|
||||
|
||||
#pragma -w3
|
||||
#pragma -km+
|
||||
#pragma -ko+
|
||||
|
||||
PROCEDURE Main()
|
||||
|
||||
LOCAL cVCS := VCSDetect()
|
||||
|
||||
LOCAL aChanges := DoctorChanges( cVCS, Changes( cVCS ) )
|
||||
LOCAL cLog
|
||||
LOCAL cLogNew
|
||||
LOCAL cLine
|
||||
LOCAL nOffset
|
||||
LOCAL cHit
|
||||
LOCAL nPos
|
||||
LOCAL cMyName
|
||||
LOCAL cOldLang
|
||||
LOCAL cLogName
|
||||
|
||||
IF Empty( aChanges )
|
||||
OutStd( hb_ProgName() + ": no changes" + hb_eol() )
|
||||
RETURN
|
||||
ENDIF
|
||||
|
||||
// ;
|
||||
|
||||
IF ! Empty( GetEnv( _CONFIGENV_ ) )
|
||||
cMyName := GetEnv( _CONFIGENV_ )
|
||||
ELSEIF hb_FileExists( _CONFIGFIL_ )
|
||||
cMyName := AllTrim( hb_MemoRead( _CONFIGFIL_ ) )
|
||||
ELSE
|
||||
cMyName := "Firstname Lastname (me domain.net)"
|
||||
ENDIF
|
||||
|
||||
nOffset := hb_UTCOffset()
|
||||
|
||||
cLogNew := hb_StrFormat( "%1$s UTC%2$s%3$02d%4$02d %5$s", ;
|
||||
hb_TToC( hb_DateTime(), "YYYY-MM-DD", "HH:MM" ), ;
|
||||
iif( nOffset < 0, "-", "+" ), ;
|
||||
Int( nOffset / 3600 ), ;
|
||||
Int( ( ( nOffset / 3600 ) - Int( nOffset / 3600 ) ) * 60 ), ;
|
||||
cMyName ) + hb_eol()
|
||||
|
||||
FOR EACH cLine IN aChanges
|
||||
cLogNew += cLine + hb_eol()
|
||||
NEXT
|
||||
|
||||
// ;
|
||||
|
||||
IF ! hb_FileExists( cLogName := "ChangeLog.txt" )
|
||||
IF ! hb_FileExists( cLogName := "ChangeLog" )
|
||||
OutStd( hb_ProgName() + ": can't find ChangeLog file" + hb_eol() )
|
||||
RETURN
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
cLog := MemoRead( cLogName )
|
||||
cOldLang := hb_cdpSelect( "EN" )
|
||||
cHit := hb_AtX( "\n[1-2][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9] UTC[\-+][0-1][0-9][0-5][0-9] ", cLog )
|
||||
IF Empty( cHit )
|
||||
cHit := ""
|
||||
ENDIF
|
||||
hb_cdpSelect( cOldLang )
|
||||
|
||||
nPos := At( AllTrim( cHit ), cLog )
|
||||
IF nPos > 0
|
||||
cLog := Left( cLog, nPos - 1 ) + cLogNew + hb_eol() + SubStr( cLog, nPos )
|
||||
ELSE
|
||||
cLog += hb_eol() + cLogNew
|
||||
ENDIF
|
||||
|
||||
hb_MemoWrit( cLogName, cLog )
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION VCSDetect()
|
||||
|
||||
DO CASE
|
||||
CASE hb_DirExists( ".svn" ) ; RETURN "svn"
|
||||
CASE hb_DirExists( ".git" ) ; RETURN "git"
|
||||
/* to make it work in an unmodified GIT repo. Ideally, all
|
||||
files/dirs should be moved one dir up, removing the top
|
||||
'harbour' directory. */
|
||||
CASE hb_DirExists( ".." + hb_ps() + ".git" ) ; RETURN "git"
|
||||
ENDCASE
|
||||
|
||||
RETURN ""
|
||||
|
||||
STATIC FUNCTION DoctorChanges( cVCS, aChanges )
|
||||
|
||||
LOCAL cLine
|
||||
LOCAL cStart
|
||||
LOCAL aNew := {}
|
||||
|
||||
ASort( aChanges,,, {| x, y | x < y } )
|
||||
|
||||
DO CASE
|
||||
CASE cVCS == "svn"
|
||||
|
||||
FOR EACH cLine IN aChanges
|
||||
IF ! Empty( cLine ) .AND. SubStr( cLine, 8, 1 ) == " "
|
||||
cStart := Left( cLine, 1 )
|
||||
SWITCH cStart
|
||||
CASE "M"
|
||||
CASE " " /* modified props */
|
||||
cStart := "*"
|
||||
EXIT
|
||||
CASE "A"
|
||||
cStart := "+"
|
||||
EXIT
|
||||
CASE "D"
|
||||
cStart := "-"
|
||||
EXIT
|
||||
CASE "X"
|
||||
cStart := ""
|
||||
EXIT
|
||||
OTHERWISE
|
||||
cStart := "?"
|
||||
ENDSWITCH
|
||||
IF ! Empty( cStart )
|
||||
AAdd( aNew, " " + cStart + " " + StrTran( SubStr( cLine, 8 + 1 ), "\", "/" ) )
|
||||
ENDIF
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
CASE cVCS == "git"
|
||||
|
||||
FOR EACH cLine IN aChanges
|
||||
IF ! Empty( cLine ) .AND. SubStr( cLine, 3, 1 ) == " "
|
||||
cStart := Left( cLine, 1 )
|
||||
IF Empty( Left( cLine, 1 ) )
|
||||
cStart := SubStr( cLine, 2, 1 )
|
||||
ENDIF
|
||||
SWITCH cStart
|
||||
CASE " "
|
||||
CASE "?"
|
||||
cStart := ""
|
||||
EXIT
|
||||
CASE "M"
|
||||
CASE "R"
|
||||
CASE "T"
|
||||
CASE "U"
|
||||
cStart := "*"
|
||||
EXIT
|
||||
CASE "A"
|
||||
CASE "C"
|
||||
cStart := "+"
|
||||
EXIT
|
||||
CASE "D"
|
||||
cStart := "-"
|
||||
EXIT
|
||||
OTHERWISE
|
||||
cStart := "?"
|
||||
ENDSWITCH
|
||||
IF ! Empty( cStart )
|
||||
AAdd( aNew, " " + cStart + " " + StrTran( SubStr( cLine, 3 + 1 ), "\", "/" ) )
|
||||
ENDIF
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
ENDCASE
|
||||
|
||||
RETURN aNew
|
||||
|
||||
STATIC FUNCTION Shell()
|
||||
|
||||
LOCAL cShell
|
||||
|
||||
#if defined( __PLATFORM__UNIX )
|
||||
cShell := GetEnv( "SHELL" )
|
||||
#else
|
||||
cShell := GetEnv( "COMSPEC" )
|
||||
#endif
|
||||
|
||||
IF ! Empty( cShell )
|
||||
#if defined( __PLATFORM__UNIX )
|
||||
cShell += " -c"
|
||||
#else
|
||||
cShell += " /c"
|
||||
#endif
|
||||
ENDIF
|
||||
|
||||
RETURN cShell
|
||||
|
||||
STATIC FUNCTION CmdEscape( cCmd )
|
||||
|
||||
#if defined( __PLATFORM__UNIX )
|
||||
cCmd := '"' + cCmd + '"'
|
||||
#endif
|
||||
|
||||
RETURN cCmd
|
||||
|
||||
STATIC FUNCTION Changes( cVCS )
|
||||
|
||||
LOCAL cStdOut := ""
|
||||
|
||||
DO CASE
|
||||
CASE cVCS == "svn" ; hb_processRun( Shell() + " " + CmdEscape( "svn status -q" ),, @cStdOut )
|
||||
CASE cVCS == "git" ; hb_processRun( Shell() + " " + CmdEscape( "git status -s" ),, @cStdOut )
|
||||
ENDCASE
|
||||
|
||||
RETURN hb_ATokens( StrTran( cStdOut, Chr( 13 ) ), Chr( 10 ) )
|
||||
620
bin/harbour.ucf
Normal file
620
bin/harbour.ucf
Normal file
@@ -0,0 +1,620 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# uncrustify config file for Harbour C sources.
|
||||
# http://uncrustify.sourceforge.net/
|
||||
#
|
||||
# Viktor Szakats (harbour syenar.net)
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
indent_with_tabs = 0 # 1=indent to level only, 2=indent with tabs
|
||||
align_with_tabs = false # use tabs to align
|
||||
align_on_tabstop = false # align on tabstops
|
||||
input_tab_size = 8 # original tab size
|
||||
output_tab_size = 3 # new tab size
|
||||
indent_columns = output_tab_size
|
||||
indent_switch_case = indent_columns
|
||||
indent_label = 2 # pos: absolute col, neg: relative column
|
||||
utf8_bom = remove # ignore/add/remove/force
|
||||
|
||||
#
|
||||
# inter-symbol newlines
|
||||
#
|
||||
|
||||
nl_enum_brace = force # "enum {" vs "enum \n {"
|
||||
nl_union_brace = force # "union {" vs "union \n {"
|
||||
nl_struct_brace = force # "struct {" vs "struct \n {"
|
||||
nl_do_brace = force # "do {" vs "do \n {"
|
||||
nl_if_brace = force # "if () {" vs "if () \n {"
|
||||
nl_for_brace = force # "for () {" vs "for () \n {"
|
||||
nl_else_brace = force # "else {" vs "else \n {"
|
||||
nl_while_brace = force # "while () {" vs "while () \n {"
|
||||
nl_switch_brace = force # "switch () {" vs "switch () \n {"
|
||||
nl_brace_while = force # "} while" vs "} \n while" - cuddle while
|
||||
nl_brace_else = force # "} else" vs "} \n else" - cuddle else
|
||||
nl_func_var_def_blk = 1
|
||||
nl_fcall_brace = force # "list_for_each() {" vs "list_for_each()\n{"
|
||||
nl_fdef_brace = force # "int foo() {" vs "int foo()\n{"
|
||||
# nl_after_return = true;
|
||||
# nl_before_case = 1
|
||||
nl_end_of_file = force # ignore/add/remove/force
|
||||
nl_end_of_file_min = 1 # number
|
||||
# nl_multi_line_define = true
|
||||
nl_max = 3
|
||||
|
||||
#
|
||||
# Source code modifications
|
||||
#
|
||||
|
||||
mod_paren_on_return = remove # "return 1;" vs "return (1);"
|
||||
# mod_full_brace_if = remove # "if (a) a--;" vs "if (a) { a--; }"
|
||||
# mod_full_brace_for = remove # "for () a--;" vs "for () { a--; }"
|
||||
# mod_full_brace_do = remove # "do a--; while ();" vs "do { a--; } while ();"
|
||||
# mod_full_brace_while = remove # "while (a) a--;" vs "while (a) { a--; }"
|
||||
|
||||
# Add or remove braces on single-line 'do' statement
|
||||
mod_full_brace_do = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove braces on single-line 'for' statement
|
||||
mod_full_brace_for = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove braces on single-line function definitions. (Pawn)
|
||||
mod_full_brace_function = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.
|
||||
mod_full_brace_if = ignore # ignore/add/remove/force
|
||||
|
||||
# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.
|
||||
# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed.
|
||||
mod_full_brace_if_chain = false # false/true
|
||||
|
||||
# Don't remove braces around statements that span N newlines
|
||||
mod_full_brace_nl = 0 # number
|
||||
|
||||
# Add or remove braces on single-line 'while' statement
|
||||
mod_full_brace_while = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove braces on single-line 'using ()' statement
|
||||
mod_full_brace_using = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove unnecessary paren on 'return' statement
|
||||
mod_paren_on_return = remove # ignore/add/remove/force
|
||||
|
||||
# Whether to change optional semicolons to real semicolons
|
||||
mod_pawn_semicolon = false # false/true
|
||||
|
||||
# Add parens on 'while' and 'if' statement around bools
|
||||
mod_full_paren_if_bool = false # false/true
|
||||
|
||||
# Whether to remove superfluous semicolons
|
||||
mod_remove_extra_semicolon = true # false/true
|
||||
|
||||
# If a function body exceeds the specified number of newlines and doesn't have a comment after
|
||||
# the close brace, a comment will be added.
|
||||
mod_add_long_function_closebrace_comment = 0 # number
|
||||
|
||||
# If a switch body exceeds the specified number of newlines and doesn't have a comment after
|
||||
# the close brace, a comment will be added.
|
||||
mod_add_long_switch_closebrace_comment = 0 # number
|
||||
|
||||
# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after
|
||||
# the #else, a comment will be added.
|
||||
mod_add_long_ifdef_endif_comment = 0 # number
|
||||
|
||||
# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after
|
||||
# the #endif, a comment will be added.
|
||||
mod_add_long_ifdef_else_comment = 0 # number
|
||||
|
||||
# If TRUE, will sort consecutive single-line 'import' statements [Java, D]
|
||||
mod_sort_import = false # false/true
|
||||
|
||||
# If TRUE, will sort consecutive single-line 'using' statements [C#]
|
||||
mod_sort_using = false # false/true
|
||||
|
||||
# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
|
||||
# This is generally a bad idea, as it may break your code.
|
||||
mod_sort_include = false # false/true
|
||||
|
||||
# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace.
|
||||
mod_move_case_break = false # false/true
|
||||
|
||||
# Will add or remove the braces around a fully braced case statement.
|
||||
# Will only remove the braces if there are no variable declarations in the block.
|
||||
mod_case_brace = remove # ignore/add/remove/force
|
||||
|
||||
# If TRUE, it will remove a void 'return;' that appears as the last statement in a function.
|
||||
mod_remove_empty_return = true # false/true
|
||||
|
||||
|
||||
#
|
||||
# inter-character spacing options
|
||||
#
|
||||
|
||||
# sp_return_paren = force # "return (1);" vs "return(1);"
|
||||
sp_sizeof_paren = remove # "sizeof (int)" vs "sizeof(int)"
|
||||
sp_before_sparen = remove # "if (" vs "if("
|
||||
sp_after_sparen = force # "if () {" vs "if (){"
|
||||
sp_after_cast = force # "(int) a" vs "(int)a"
|
||||
sp_inside_braces = add # "{ 1 }" vs "{1}"
|
||||
sp_inside_braces_struct = add # "{ 1 }" vs "{1}"
|
||||
sp_inside_braces_enum = add # "{ 1 }" vs "{1}"
|
||||
sp_assign = add
|
||||
sp_arith = add
|
||||
sp_bool = add
|
||||
sp_compare = add
|
||||
sp_assign = add
|
||||
sp_after_comma = add
|
||||
sp_func_def_paren = remove # "int foo (){" vs "int foo(){"
|
||||
sp_func_call_paren = remove # "foo (" vs "foo("
|
||||
sp_func_proto_paren = remove # "int foo ();" vs "int foo();"
|
||||
|
||||
#
|
||||
# Spacing options
|
||||
#
|
||||
|
||||
# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
|
||||
sp_arith = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around assignment operator '=', '+=', etc
|
||||
sp_assign = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around assignment operator '=' in a prototype
|
||||
sp_assign_default = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign.
|
||||
sp_before_assign = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign.
|
||||
sp_after_assign = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around assignment '=' in enum
|
||||
sp_enum_assign = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign.
|
||||
sp_enum_before_assign = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign.
|
||||
sp_enum_after_assign = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around preprocessor '##' concatenation operator. Default=Add
|
||||
sp_pp_concat = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. Default=Add
|
||||
sp_pp_stringify = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around boolean operators '&&' and '||'
|
||||
sp_bool = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around compare operator '<', '>', '==', etc
|
||||
sp_compare = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside '(' and ')'
|
||||
sp_inside_paren = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between nested parens
|
||||
sp_paren_paren = force # ignore/add/remove/force
|
||||
|
||||
# Whether to balance spaces inside nested parens ???
|
||||
sp_balance_nested_parens = false # false/true
|
||||
|
||||
# Add or remove space between ')' and '{'
|
||||
sp_paren_brace = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before pointer star '*'
|
||||
sp_before_ptr_star = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before pointer star '*' that isn't followed by a variable name
|
||||
# If set to 'ignore', sp_before_ptr_star is used instead. ??????
|
||||
sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between pointer stars '*'
|
||||
sp_between_ptr_star = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after pointer star '*', if followed by a word.
|
||||
sp_after_ptr_star = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after a pointer star '*', if followed by a func proto/def.
|
||||
sp_after_ptr_star_func = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a pointer star '*', if followed by a func proto/def.
|
||||
sp_before_ptr_star_func = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a reference sign '&'
|
||||
sp_before_byref = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a reference sign '&' that isn't followed by a variable name
|
||||
# If set to 'ignore', sp_before_byref is used instead.
|
||||
sp_before_unnamed_byref = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after reference sign '&', if followed by a word.
|
||||
sp_after_byref = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after a reference sign '&', if followed by a func proto/def.
|
||||
sp_after_byref_func = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a reference sign '&', if followed by a func proto/def.
|
||||
sp_before_byref_func = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between type and word. Default=Force
|
||||
sp_after_type = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space in 'template <' vs 'template<'.
|
||||
# If set to ignore, sp_before_angle is used.
|
||||
sp_template_angle = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before '<>'
|
||||
sp_before_angle = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside '<' and '>'
|
||||
sp_inside_angle = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after '<>'
|
||||
sp_after_angle = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '<>' and '(' as found in 'new List<byte>();'
|
||||
sp_angle_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '<>' and a word as in 'List<byte> m;'
|
||||
sp_angle_word = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add
|
||||
sp_angle_shift = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
|
||||
sp_before_sparen = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside if-condition '(' and ')'
|
||||
sp_inside_sparen = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before if-condition ')'. Overrides sp_inside_sparen.
|
||||
sp_inside_sparen_close = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
|
||||
sp_after_sparen = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
|
||||
sp_sparen_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'invariant' and '(' in the D language.
|
||||
sp_invariant_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the ')' in 'invariant (C) c' in the D language.
|
||||
sp_after_invariant_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before empty statement ';' on 'if', 'for' and 'while'
|
||||
sp_special_semi = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before ';'. Default=Remove
|
||||
sp_before_semi = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before ';' in non-empty 'for' statements
|
||||
sp_before_semi_for = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a semicolon of an empty part of a for statement.
|
||||
sp_before_semi_for_empty = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after ';', except when followed by a comment. Default=Add
|
||||
sp_after_semi = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after ';' in non-empty 'for' statements. Default=Force
|
||||
sp_after_semi_for = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; <here> ).
|
||||
sp_after_semi_for_empty = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before '[' (except '[]')
|
||||
sp_before_square = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before '[]'
|
||||
sp_before_squares = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside '[' and ']'
|
||||
sp_inside_square = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after ','
|
||||
sp_after_comma = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before ','
|
||||
sp_before_comma = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between an open paren and comma: '(,' vs '( ,'
|
||||
sp_paren_comma = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before the variadic '...' when preceded by a non-punctuator
|
||||
sp_before_ellipsis = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after class ':'
|
||||
sp_after_class_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before class ':'
|
||||
sp_before_class_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before case ':'. Default=Remove
|
||||
sp_before_case_colon = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'operator' and operator sign
|
||||
sp_after_operator = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between the operator symbol and the open paren, as in 'operator ++('
|
||||
sp_after_operator_sym = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a'
|
||||
sp_after_cast = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove spaces inside cast parens
|
||||
sp_inside_paren_cast = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)'
|
||||
sp_cpp_cast_paren = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'sizeof' and '('
|
||||
sp_sizeof_paren = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the tag keyword (Pawn)
|
||||
sp_after_tag = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside enum '{' and '}'
|
||||
sp_inside_braces_enum = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside struct/union '{' and '}'
|
||||
sp_inside_braces_struct = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside '{' and '}'
|
||||
sp_inside_braces = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside '{}'
|
||||
sp_inside_braces_empty = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between return type and function name
|
||||
# A minimum of 1 is forced except for pointer return types.
|
||||
sp_type_func = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between function name and '(' on function declaration
|
||||
sp_func_proto_paren = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between function name and '(' on function definition
|
||||
sp_func_def_paren = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside empty function '()'
|
||||
sp_inside_fparens = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside function '(' and ')'
|
||||
sp_inside_fparen = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between ']' and '(' when part of a function call.
|
||||
sp_square_fparen = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between ')' and '{' of function
|
||||
sp_fparen_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between function name and '(' on function calls
|
||||
sp_func_call_paren = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between function name and '()' on function calls without parameters.
|
||||
# If set to 'ignore' (the default), sp_func_call_paren is used.
|
||||
sp_func_call_paren_empty = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between the user function name and '(' on function calls
|
||||
# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file.
|
||||
sp_func_call_user_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between a constructor/destructor and the open paren
|
||||
sp_func_class_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'return' and '('
|
||||
sp_return_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '__attribute__' and '('
|
||||
sp_attribute_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'defined' and '(' in '#if defined (FOO)'
|
||||
sp_defined_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'throw' and '(' in 'throw (something)'
|
||||
sp_throw_paren = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between macro and value
|
||||
sp_macro = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between macro function ')' and value
|
||||
sp_macro_func = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'else' and '{' if on the same line
|
||||
sp_else_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '}' and 'else' if on the same line
|
||||
sp_brace_else = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '}' and the name of a typedef on the same line
|
||||
sp_brace_typedef = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'catch' and '{' if on the same line
|
||||
sp_catch_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '}' and 'catch' if on the same line
|
||||
sp_brace_catch = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'finally' and '{' if on the same line
|
||||
sp_finally_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '}' and 'finally' if on the same line
|
||||
sp_brace_finally = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between 'try' and '{' if on the same line
|
||||
sp_try_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between get/set and '{' if on the same line
|
||||
sp_getset_brace = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before the '::' operator
|
||||
sp_before_dc = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the '::' operator
|
||||
sp_after_dc = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove around the D named array initializer ':' operator
|
||||
sp_d_array_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the '!' (not) operator. Default=Remove
|
||||
sp_not = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the '~' (invert) operator. Default=Remove
|
||||
sp_inv = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the '&' (address-of) operator. Default=Remove
|
||||
# This does not affect the spacing after a '&' that is part of a type.
|
||||
sp_addr = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around the '.' or '->' operators. Default=Remove
|
||||
sp_member = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the '*' (dereference) operator. Default=Remove
|
||||
# This does not affect the spacing after a '*' that is part of a type.
|
||||
sp_deref = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove
|
||||
sp_sign = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove
|
||||
sp_incdec = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a backslash-newline at the end of a line. Default=Add
|
||||
sp_before_nl_cont = add # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'
|
||||
sp_after_oc_scope = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the colon in message specs
|
||||
# '-(int) f:(int) x;' vs '-(int) f: (int) x;'
|
||||
sp_after_oc_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before the colon in message specs
|
||||
# '-(int) f: (int) x;' vs '-(int) f : (int) x;'
|
||||
sp_before_oc_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the colon in message specs
|
||||
# '[object setValue:1];' vs '[object setValue: 1];'
|
||||
sp_after_send_oc_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before the colon in message specs
|
||||
# '[object setValue:1];' vs '[object setValue :1];'
|
||||
sp_before_send_oc_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the (type) in message specs
|
||||
# '-(int)f: (int) x;' vs '-(int)f: (int)x;'
|
||||
sp_after_oc_type = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after the first (type) in message specs
|
||||
# '-(int) f:(int)x;' vs '-(int)f:(int)x;'
|
||||
sp_after_oc_return_type = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '@selector' and '('
|
||||
# '@selector(msgName)' vs '@selector (msgName)'
|
||||
# Also applies to @protocol() constructs
|
||||
sp_after_oc_at_sel = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between '@selector(x)' and the following word
|
||||
# '@selector(foo) a:' vs '@selector(foo)a:'
|
||||
sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space inside '@selector' parens
|
||||
# '@selector(foo)' vs '@selector( foo )'
|
||||
# Also applies to @protocol() constructs
|
||||
sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space before a block pointer caret
|
||||
# '^int (int arg){...}' vs. ' ^int (int arg){...}'
|
||||
sp_before_oc_block_caret = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after a block pointer caret
|
||||
# '^int (int arg){...}' vs. '^ int (int arg){...}'
|
||||
sp_after_oc_block_caret = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around the ':' in 'b ? t : f'
|
||||
sp_cond_colon = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space around the '?' in 'b ? t : f'
|
||||
sp_cond_question = ignore # ignore/add/remove/force
|
||||
|
||||
# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here.
|
||||
sp_case_label = ignore # ignore/add/remove/force
|
||||
|
||||
# Control the space around the D '..' operator.
|
||||
sp_range = ignore # ignore/add/remove/force
|
||||
|
||||
# Control the space after the opening of a C++ comment '// A' vs '//A'
|
||||
sp_cmt_cpp_start = ignore # ignore/add/remove/force
|
||||
|
||||
# Controls the spaces between #else or #endif and a trailing comment
|
||||
sp_endif_cmt = ignore # ignore/add/remove/force
|
||||
|
||||
|
||||
#
|
||||
# Aligning stuff
|
||||
#
|
||||
|
||||
align_enum_equ_span = 4 # '=' in enum definition
|
||||
# align_nl_cont = true
|
||||
# align_var_def_inline = true
|
||||
# align_var_def_star = false
|
||||
# align_var_def_colon = true
|
||||
align_var_struct_thresh = 8
|
||||
align_var_struct_span = 1
|
||||
align_var_struct_gap = 1
|
||||
align_var_def_thresh = 8
|
||||
align_var_def_span = 1
|
||||
align_var_def_gap = 1
|
||||
align_assign_thresh = 8
|
||||
align_assign_span = 1
|
||||
align_struct_init_span = 3 # align stuff in a structure init '= { }'
|
||||
align_right_cmt_span = 3
|
||||
align_pp_define_span = 8
|
||||
align_pp_define_gap = 2
|
||||
|
||||
# cmt_star_cont = false
|
||||
|
||||
# indent_brace = 0
|
||||
|
||||
|
||||
#
|
||||
# Line Splitting options
|
||||
#
|
||||
|
||||
# Try to limit code width to N number of columns
|
||||
code_width = 0 # number
|
||||
|
||||
# Whether to fully split long 'for' statements at semi-colons
|
||||
ls_for_split_full = false # false/true
|
||||
|
||||
# Whether to fully split long function protos/calls at commas
|
||||
ls_func_split_full = false # false/true
|
||||
|
||||
#
|
||||
# Preprocessor options
|
||||
#
|
||||
|
||||
# Control indent of preprocessors inside #if blocks at brace level 0
|
||||
pp_indent = ignore # ignore/add/remove/force
|
||||
|
||||
# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)
|
||||
pp_indent_at_level = false # false/true
|
||||
|
||||
# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1.
|
||||
pp_indent_count = 1 # number
|
||||
|
||||
# Add or remove space after # based on pp_level of #if blocks
|
||||
pp_space = ignore # ignore/add/remove/force
|
||||
|
||||
# Sets the number of spaces added with pp_space
|
||||
pp_space_count = 0 # number
|
||||
|
||||
# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level
|
||||
pp_indent_if = 0 # number
|
||||
|
||||
# Control whether to indent the code between #if, #else and #endif when not at file-level
|
||||
pp_if_indent_code = false # false/true
|
||||
|
||||
# Whether to indent '#define' at the brace level (true) or from column 1 (false)
|
||||
pp_define_at_level = false # false/true
|
||||
Reference in New Issue
Block a user