Files
harbour-core/bin/check.hb
Viktor Szakats b9d69aa3f5 2013-04-02 17:49 UTC+0200 Viktor Szakats (harbour syenar.net)
+ bin/check.hb
    + new source verifier. Able to all documented (and more)
      required text file and filename properties.

  * bin/commit.hb
    + added feature to verify all files to be committed to
      conform with certain naming and text file content rules
    + added some more feedback

  * config/postinst.hb
    + include commit.hb and check.hb in 'install'

  * include/extend.h
  * contrib/hbcairo/paths.c
  * contrib/hbcairo/png.c
  * contrib/hbcairo/util.c
  * contrib/hbtpathy/readme.txt
  * tests/harbour.ini
  * tests/parseins.ini
    ! multiple EOL at EOF

  * contrib/hbhpdf/tests/files/cp932.txt
  * contrib/hbhpdf/tests/files/cp936.txt
  * contrib/hbhpdf/tests/files/elic_jp.txt
    ! line ending spaces
    ! missing EOL at EOF

  * contrib/hbhttpd/tests/tpl/app/account/edit.tpl
  * contrib/hbhttpd/tests/tpl/app/login.tpl
  * contrib/hbhttpd/tests/tpl/app/logout.tpl
  * contrib/hbhttpd/tests/tpl/app/main.tpl
  * contrib/hbhttpd/tests/tpl/app/register.tpl
  * lib/3rd/win/bcc/unicows_license.txt
  * lib/3rd/win/mingw/libunicows_license.txt
    ! missing EOL at EOF

  * COPYING.txt
  * src/rtl/gtcrs/hb-charmap.def
  * tests/big5_gen.prg
    ! tabs

  * extras/gfspell/spell.prg
  * src/rtl/gtwin/gtwin.c
    ! ASCII 127

  * src/codepage/cp_tpl.c
    ! converted to UTF-8 (just guessing what the original CP was)

  * src/pp/hbpp.c
    ! do not generate SVN header in hbverbld.h
    + avoid SVN header string in source as is to miss matched
      in source verifier

  * src/vm/extrap.c
    ! do not generate whitespace at EOL in output

  * tests/lang2po.hb
  * tests/po2lang.hb
    + minor improvements
    ! fixed to generate consistent EOL

  * bin/3rdpatch.hb
    * newline at top deleted

  * extras/hbdoc/hbdoc.hbp
  * extras/hbdoc/hbdoc.prg
  * extras/hbdoc/_tmplates.prg -> extras/hbdoc/_tmplate.prg
  * contrib/hbcairo/tests/lightning.prg -> contrib/hbcairo/tests/lightnin.prg
    ! long filename

  * .gitattributes
  * extras/guestbk/guestbk.prg
  * extras/guestbk/guestbk.txt
  * extras/guestbk/guestbk.htm -> extras/guestbk/guestbk.html
    * deleted .htm file, now all HTML has extension .html
    * .exe references in doc made OS neutral
    ; Can only be used on non-MS-DOS systems, so it's okay
2013-04-02 17:50:36 +02:00

383 lines
10 KiB
Plaintext

#!/usr/bin/hbmk2
/*
* Harbour Project source code:
* Various validations of filenames and file content, meant to be
* run before committing to repository.
*
* Copyright 2013 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/).
*
*/
#pragma -w3
#pragma -km+
#pragma -ko+
#include "directry.ch"
FUNCTION CheckFileList( xName )
LOCAL lPassed := .T.
LOCAL aErr, s
LOCAL file
IF HB_ISSTRING( xName )
xName := { xName }
ENDIF
IF Empty( xName ) .OR. HB_ISARRAY( xName )
IF Empty( xName )
xName := hb_DirScan( "", hb_osFileMask() )
FOR EACH file IN xName
file := file[ F_NAME ]
NEXT
ENDIF
FOR EACH file IN xName
IF ! CheckFile( file, @aErr )
lPassed := .F.
FOR EACH s IN aErr
OutStd( file + ": " + s + hb_eol() )
NEXT
ENDIF
NEXT
ENDIF
RETURN lPassed
STATIC FUNCTION CheckFile( cName, /* @ */ aErr )
LOCAL cFile
LOCAL tmp
LOCAL cEOL
LOCAL aCanBeUpper := { ;
"Makefile", ;
"README.md", ;
"COPYING.txt", ;
"*/RELNOTES.txt", ;
"*/HARBOUR_README_*.txt", ;
"ChangeLog.txt", ;
"*.po", ;
"*.md" }
LOCAL aCanBeDot := { ;
".travis.yml", ;
".git*" }
LOCAL aCanBeLong := { ;
"ChangeLog.txt", ;
".git*", ;
"*.po", ;
"*.md", ;
"*.html", ;
"*/hb-charmap.def", ; /* TOFIX: Use 8.3 name */
"package/*", ;
"*/3rd/*", ;
"contrib/hbwin/*", ;
"contrib/rddads/unixutils.h", ;
"extras/httpsrv/*" }
LOCAL aCanHaveTab := { ;
"Makefile", ;
"*.mk", ;
"*.yyc", ;
"*.dif", ;
"*.xml", ;
"*.css" }
LOCAL aCanHaveSpaceAtEol := { ;
"*.dif", ;
"*.md" }
LOCAL aCanHaveAnyEncoding := { ;
"*.dif", ;
"contrib/hbmisc/tests/sample.txt", ; /* TOFIX: Not Unicode compatible component */
"contrib/hbhpdf/tests/files/*.txt" }
LOCAL aForcedCRLF := { ;
"*.bat" }
LOCAL aForcedLF := { ;
"*.sh" }
cName := hb_DirSepToOS( cName )
cFile := hb_MemoRead( cName )
aErr := {}
/* filename checks */
IF ! FNameExc( cName, LoadGitIgnore() )
IF ( Len( hb_FNameName( cName ) ) > 8 .OR. Len( hb_FNameExt( cName ) ) > 4 ) .AND. ! FNameExc( cName, aCanBeLong )
AAdd( aErr, "filename: non-8.3" )
ENDIF
IF Left( hb_FNameName( cName ), 1 ) == "." .AND. ! FNameExc( cName, aCanBeDot )
AAdd( aErr, "filename: non MS-DOS compatible" )
ENDIF
IF !( cName == Lower( cName ) ) .AND. ! FNameExc( cName, aCanBeUpper )
AAdd( aErr, "filename: non-lowercase" )
ENDIF
IF ! IsASCII7( cName )
AAdd( aErr, "filename: non-ASCII-7" )
ENDIF
IF IsBinary( cFile )
IF .F.
IF hb_FNameExt( cFile ) == ".png"
OutStd( cFile + ": " + "content: optimizing" + hb_eol() )
hb_run( "optipng " + cFile )
ENDIF
ENDIF
ELSE
IF hb_FileMatch( cName, "ChangeLog.txt" ) .AND. Len( cFile ) > 32768
cFile := Left( cFile, 16384 ) + Right( cFile, 16384 )
ENDIF
/* text content checks */
IF ! FNameExc( cName, aCanHaveTab ) .AND. e"\t" $ cFile
AAdd( aErr, "content: has tab" )
ENDIF
IF hb_BLeft( cFile, Len( UTF8_BOM() ) ) == UTF8_BOM()
AAdd( aErr, "content: has BOM" )
ENDIF
IF ! FNameExc( cName, aCanHaveSpaceAtEol ) .AND. EndingWhitespace( cFile )
AAdd( aErr, "content: has ending whitespace" )
ENDIF
IF Right( cFile, 1 ) == Chr( 26 )
AAdd( aErr, "content: has legacy EOF char" )
ENDIF
cEOL := EOLDetect( cFile )
IF Len( cEOL ) == 0
AAdd( aErr, "content: has mixed EOL types" )
ENDIF
IF FNameExc( cName, aForcedCRLF ) .AND. !( cEOL == Chr( 13 ) + Chr( 10 ) )
AAdd( aErr, "content: must use CRLF EOL for file type" )
ENDIF
IF FNameExc( cName, aForcedLF ) .AND. !( cEOL == Chr( 10 ) )
AAdd( aErr, "content: must use LF EOL for file type" )
ENDIF
IF !( Right( cFile, Len( hb_eol() ) ) == hb_eol() ) .AND. ;
!( Right( cFile, Len( e"\n" ) ) == e"\n" )
AAdd( aErr, "content: has no EOL at EOF" )
ENDIF
IF Right( cFile, 2 * Len( hb_eol() ) ) == Replicate( hb_eol(), 2 )
AAdd( aErr, "content: has multiple EOL at EOF" )
ENDIF
IF ! FNameExc( cName, aCanHaveAnyEncoding )
tmp := -1
IF ! IsASCII7( cFile, @tmp ) .AND. ! IsUTF8( cFile )
AAdd( aErr, "content: is non-UTF-8/ASCII-7: " + hb_ntos( tmp ) )
ENDIF
ENDIF
IF "$" + "Id" $ cFile .AND. ! hb_FileMatch( cName, "ChangeLog.txt" )
AAdd( aErr, "content: has " + "$" + "Id" )
ENDIF
ENDIF
ENDIF
RETURN Empty( aErr )
STATIC FUNCTION IsBinary( cFile )
RETURN Chr( 0 ) $ cFile .OR. !( Chr( 10 ) $ cFile )
/*
Copyright (c) 1996 Eugene Roshal
Copyright (c) 2000 Far Group
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
STATIC FUNCTION IsUTF8( cString )
LOCAL lASCII := .T.
LOCAL nOctets := 0
LOCAL nChar
LOCAL tmp
FOR EACH tmp IN cString
nChar := hb_BCode( tmp )
IF hb_bitAnd( nChar, 0x80 ) != 0
lASCII := .F.
ENDIF
IF nOctets != 0
IF hb_bitAnd( nChar, 0xC0 ) != 0x80
RETURN .F.
ENDIF
--nOctets
ELSEIF hb_bitAnd( nChar, 0x80 ) != 0
DO WHILE hb_bitAnd( nChar, 0x80 ) != 0
nChar := hb_bitAnd( hb_bitShift( nChar, 1 ), 0xFF )
++nOctets
ENDDO
--nOctets
IF nOctets == 0
RETURN .F.
ENDIF
ENDIF
NEXT
RETURN !( nOctets > 0 .OR. lASCII )
STATIC FUNCTION IsASCII7( cString, /* @ */ nChar )
LOCAL tmp
FOR EACH tmp IN cString
nChar := hb_BCode( tmp )
IF ( nChar < 32 .OR. nChar > 126 ) .AND. ;
nChar != 10 .AND. nChar != 13 .AND. nChar != 9 .AND. nChar != 12
RETURN .F.
ENDIF
NEXT
RETURN .T.
STATIC FUNCTION EOLDetect( cFile )
LOCAL nCR := 0
LOCAL nLF := 0
LOCAL tmp
FOR EACH tmp IN cFile
IF tmp == Chr( 13 )
++nCR
ELSEIF tmp == Chr( 10 )
++nLF
ENDIF
NEXT
IF nCR > 0 .AND. nLF == 0
RETURN Chr( 13 )
ELSEIF nCR == 0 .AND. nLF > 0
RETURN Chr( 10 )
ELSEIF nCR == nLF
RETURN Chr( 13 ) + Chr( 10 )
ENDIF
RETURN ""
STATIC FUNCTION EndingWhitespace( cFile )
LOCAL cLine
FOR EACH cLine IN hb_ATokens( StrTran( cFile, Chr( 13 ) ), Chr( 10 ) )
IF Right( cLine, 1 ) == " "
RETURN .T.
ENDIF
NEXT
RETURN .F.
STATIC FUNCTION FNameExc( cName, aList )
LOCAL tmp, tmp1
FOR EACH tmp IN aList
IF !( Left( tmp, 1 ) == "!" ) .AND. hb_FileMatch( cName, hb_DirSepToOS( tmp ) )
FOR EACH tmp1 IN aList
IF Left( tmp1, 1 ) == "!" .AND. hb_FileMatch( cName, hb_DirSepToOS( SubStr( tmp1, 2 ) ) )
RETURN .F.
ENDIF
NEXT
RETURN .T.
ENDIF
NEXT
RETURN .F.
STATIC FUNCTION UTF8_BOM()
RETURN ;
hb_BChar( 0xEF ) + ;
hb_BChar( 0xBB ) + ;
hb_BChar( 0xBF )
STATIC FUNCTION LoadGitIgnore()
THREAD STATIC s_aIgnore := NIL
LOCAL cLine
IF s_aIgnore == NIL
s_aIgnore := { "*/3rd/*" }
FOR EACH cLine IN hb_ATokens( StrTran( hb_MemoRead( ".gitignore" ), Chr( 13 ) ), Chr( 10 ) )
IF ! Empty( cLine ) .AND. !( Left( cLine, 1 ) == "#" )
/* TODO: clean this */
AAdd( s_aIgnore, ;
iif( Left( cLine, 1 ) $ "?*/!", "", "*/" ) + ;
cLine + ;
iif( Right( cLine, 1 ) == "/", "*", ;
iif( Empty( hb_FNameExt( cLine ) ) .AND. !( Right( cLine, 2 ) == "*/" ), "/*", "" ) ) )
IF !( ATail( s_aIgnore ) == cLine )
IF Left( ATail( s_aIgnore ), 2 ) == "*/"
AAdd( s_aIgnore, SubStr( ATail( s_aIgnore ), 3 ) )
ENDIF
AAdd( s_aIgnore, cLine )
ENDIF
ENDIF
NEXT
ENDIF
RETURN s_aIgnore