2010-04-21 03:18:32 +05:30
|
|
|
#
|
|
|
|
# Gramps - a GTK+ based genealogy program
|
|
|
|
#
|
|
|
|
# Copyright (C) 2006 Brian Matherly
|
|
|
|
# Copyright (C) 2008 Stephen George
|
|
|
|
#
|
|
|
|
# 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
|
2014-08-09 07:59:07 +05:30
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2010-04-21 03:18:32 +05:30
|
|
|
#
|
|
|
|
# $Id: $
|
|
|
|
|
|
|
|
import os, glob, sys, shutil
|
|
|
|
import string
|
|
|
|
import os.path as path
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
CONFIGURE_IN = 'configure.in'
|
|
|
|
CONST_PY_IN = 'src/const.py.in'
|
|
|
|
TRANSLATE_FOLDER = 'po'
|
|
|
|
|
|
|
|
EXTRA_FILES = [ 'COPYING', 'NEWS', 'FAQ', 'AUTHORS']
|
|
|
|
|
|
|
|
FULL_COLON_SUBST = "~"
|
|
|
|
|
|
|
|
#min required version of NSIS
|
|
|
|
MIN_NSIS_VERSION = (2,42)
|
|
|
|
|
|
|
|
#tools used during build
|
|
|
|
MAKENSIS_exe = None
|
|
|
|
SVN_exe = None
|
|
|
|
po_errs = []
|
|
|
|
po_oks = []
|
|
|
|
|
|
|
|
import gobject
|
|
|
|
|
|
|
|
|
|
|
|
#==== Set up logging system
|
|
|
|
# need to also set up a logger for when run as a module.
|
|
|
|
|
|
|
|
# change to set up a console logger in module global space.
|
|
|
|
# then add the file logger later once I know the path
|
|
|
|
import logging
|
|
|
|
logging.basicConfig(level=logging.DEBUG,
|
|
|
|
format='%(asctime)s %(name)-10s %(levelname)-8s %(message)s',
|
|
|
|
datefmt='%H:%M',
|
|
|
|
filename= 'build.log', #path.join(out_dir,'build.log'),
|
|
|
|
filemode='w')
|
|
|
|
#create a Handler for the console
|
|
|
|
console = logging.StreamHandler()
|
|
|
|
console.setLevel(logging.INFO)
|
|
|
|
#Set a simle format for console
|
|
|
|
formatter = logging.Formatter('%(levelname)-8s %(message)s')
|
|
|
|
console.setFormatter(formatter)
|
|
|
|
#add the console handler to the root handler
|
|
|
|
log = logging.getLogger('BuildApp')
|
|
|
|
log.addHandler(console)
|
|
|
|
|
|
|
|
|
2012-06-18 02:55:37 +05:30
|
|
|
class buildbase(GObject.GObject):
|
2010-04-21 03:18:32 +05:30
|
|
|
__gsignals__={
|
2012-06-18 02:55:37 +05:30
|
|
|
"build_progresstext" : (GObject.SignalFlags.RUN_LAST, None, [GObject.TYPE_STRING]),
|
|
|
|
"build_progressfraction" : (GObject.SignalFlags.RUN_LAST, None, [GObject.TYPE_FLOAT]),
|
2010-04-21 03:18:32 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
def __init(self):
|
2012-06-18 02:55:37 +05:30
|
|
|
GObject.GObject.__init__(self)
|
2010-04-21 03:18:32 +05:30
|
|
|
self.gramps_version = 'VERSION-UNKNOWN'
|
|
|
|
self.bTarball = bTarball
|
|
|
|
self.build_root = '.' # the directory were the build source is located
|
|
|
|
self.out_dir = '.' # the directory to output final installer to, and the expand source to
|
|
|
|
self.repository_path = '.' #where the source comes from, either SVN root or a tarball
|
|
|
|
self.bBuildInstaller = True
|
2012-05-31 06:43:28 +05:30
|
|
|
self.tarbase3 = '.'
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
def getbuild_src(self):
|
|
|
|
return os.path.join(self.build_root, 'src')
|
|
|
|
|
|
|
|
build_src = property(getbuild_src)
|
|
|
|
|
|
|
|
def isGrampsRoot(self, root ):
|
|
|
|
log.debug( 'isGrampsRoot: %s' % root )
|
|
|
|
if path.isfile(path.join(root, CONFIGURE_IN)):
|
|
|
|
if path.isfile(path.join(root, CONST_PY_IN)):
|
|
|
|
if path.isdir(path.join(root, TRANSLATE_FOLDER)):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def getSVNRevision(self, dir ):
|
|
|
|
log.debug('========== getSVNRevision(%s)' % dir)
|
|
|
|
cmd = 'svnversion -n %s' % dir
|
|
|
|
log.debug( "Running: %s" % cmd )
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
proc = subprocess.Popen( cmd, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
2010-04-21 03:18:32 +05:30
|
|
|
log.debug( output )
|
|
|
|
if err:
|
|
|
|
for line in err.split('\n'):
|
|
|
|
log.error(line)
|
|
|
|
if not stdout:
|
|
|
|
output = '-UNKNOWN'
|
|
|
|
return 'SVN' + output
|
|
|
|
|
|
|
|
def exportSVN(self, svn_dir, destdir):
|
|
|
|
'''
|
|
|
|
svn export PATH1 PATH2
|
|
|
|
exports a clean directory tree from the working copy specified by PATH1 into PATH2.
|
|
|
|
All local changes will be preserved, but files not under version control will not be copied.
|
|
|
|
|
|
|
|
destdir cannot exist, script will clean up dir first
|
|
|
|
'''
|
|
|
|
log.debug('========== exportSVN(%s, %s)' % (svn_dir, destdir) )
|
2012-05-31 19:57:28 +05:30
|
|
|
# cmd = '"%s" export %s %s' % (SVN_exe ,svn_dir, destdir)
|
|
|
|
cmd = [SVN_exe, 'export' ,svn_dir, destdir] #'"%s" export %s %s' % (SVN_exe ,svn_dir, destdir)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
log.info( "Running: %s" % cmd)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
proc = subprocess.Popen( cmd, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
2010-04-21 03:18:32 +05:30
|
|
|
log.info( output )
|
|
|
|
if err:
|
|
|
|
log.error(err)
|
|
|
|
|
|
|
|
def copyExtraFilesToBuildDir(self, source_path):
|
|
|
|
'''
|
|
|
|
A few extra files not in src directory needs to be copied to the build dir
|
|
|
|
'''
|
|
|
|
log.debug('========== copyExtraFilesToBuildDir(%s)' % (source_path))
|
|
|
|
for file in EXTRA_FILES:
|
|
|
|
outfile = file
|
|
|
|
if file == 'NEWS':
|
|
|
|
#Jump through hoops tomake sure the end of line charactors are windows format (wont work on linux!!)
|
2016-09-01 10:22:45 +05:30
|
|
|
outfile = 'NEWS.TXT' #Lets add .TXT suffix to filename so installer knows to call notepad
|
2010-04-21 03:18:32 +05:30
|
|
|
fnews = open(os.path.join(source_path,file), 'r')
|
|
|
|
newslines = fnews.readlines()
|
|
|
|
newsout = open(os.path.join(self.build_src,outfile), 'w')
|
|
|
|
newsout.writelines(newslines)
|
|
|
|
newsout.close()
|
|
|
|
fnews.close()
|
|
|
|
else:
|
|
|
|
shutil.copy(os.path.join(source_path,file), os.path.join(self.build_src,outfile) )
|
|
|
|
|
|
|
|
def compileInstallScript(self):
|
|
|
|
'''
|
|
|
|
Now we got a build directory, lets create the installation program
|
|
|
|
'''
|
|
|
|
log.debug('========== compileInstallScript()')
|
|
|
|
log.info('Compiling NullSoft install script .... be patient')
|
|
|
|
# calc path to gramps2.nsi
|
|
|
|
# need to ensure __file__ has full path, under linux it does not.
|
|
|
|
thisfilepath = os.path.abspath(__file__)
|
|
|
|
pth = os.path.relpath(os.path.dirname( thisfilepath ), os.getcwd())
|
2016-09-01 10:22:45 +05:30
|
|
|
pth2nsis_script = os.path.join(pth, 'gramps2.nsi')
|
2010-04-21 03:18:32 +05:30
|
|
|
|
|
|
|
#should tests be more along lines of os.name which returns 'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos'
|
|
|
|
if sys.platform == 'win32':
|
2012-05-31 19:57:28 +05:30
|
|
|
# cmd = '"%s" /V3 %s' % (MAKENSIS_exe, pth2nsis_script)
|
|
|
|
cmd = [MAKENSIS_exe, '/V3',pth2nsis_script]
|
2010-04-21 03:18:32 +05:30
|
|
|
elif sys.platform == 'linux2':
|
|
|
|
#assumption makensis is installed and on the path
|
|
|
|
cmd = '%s -V3 %s' % (MAKENSIS_exe, pth2nsis_script)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
log.info( "Running: %s" % cmd)
|
|
|
|
# Need to define the following enviroment variables for NSIS script
|
|
|
|
os.environ['GRAMPS_VER'] = self.gramps_version
|
|
|
|
os.environ['GRAMPS_BUILD_DIR'] = os.path.abspath(self.build_src)
|
|
|
|
os.environ['GRAMPS_OUT_DIR'] = os.path.abspath(self.out_dir)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
proc = subprocess.Popen( cmd, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
2010-04-21 03:18:32 +05:30
|
|
|
log.info( output )
|
|
|
|
if err:
|
|
|
|
log.error(err)
|
|
|
|
|
|
|
|
def getVersionFromConfigureIn(self, repository_path):
|
|
|
|
log.debug('========== read_config_in(%s)' % repository_path)
|
|
|
|
fin = open('%s/configure.in' % repository_path, 'r')
|
|
|
|
conf_lines = fin.readlines()
|
|
|
|
fin.close()
|
|
|
|
return self.getVersionFromLines(conf_lines)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
def getVersionFromLines(self, conf_lines):
|
|
|
|
log.debug('========== getVersionFromLines()')
|
|
|
|
for line in conf_lines:
|
|
|
|
if 'AC_INIT(gramps' in line:
|
|
|
|
junk, ver, junk2 = line.split(',')
|
|
|
|
elif line[:7] == 'RELEASE':
|
|
|
|
junk,release = line.split('=')
|
|
|
|
if 'SVN$' in release:#not a release version
|
|
|
|
release = self.getSVNRevision( repository_path )
|
|
|
|
elif not self.bTarball: # This is aRelease, lets make sure svn working copy is prestine
|
|
|
|
# elif not bTarball: # This is aRelease, lets make sure svn working copy is prestine
|
|
|
|
test_num = getSVNRevision( repository_path )
|
|
|
|
if test_num.endswith('M'): # in test_num: #endsWith
|
|
|
|
log.warning('*==========================================================')
|
|
|
|
log.warning('* Building a Release from modified SVN Working Copy ')
|
|
|
|
log.warning('* ===> Creating %s-%s from %s-%s <==' % (ver.strip(), release.strip(),ver.strip(), test_num.strip()) )
|
|
|
|
log.warning('*==========================================================')
|
|
|
|
gversion = '%s-%s' % (ver.strip(), release.strip())
|
|
|
|
gversion = gversion.replace(":", FULL_COLON_SUBST) # if it's a mixed version, then need to replace the : with something else
|
|
|
|
log.info( 'GrampsVersion: %s' % gversion )
|
|
|
|
return gversion
|
|
|
|
|
|
|
|
def processPO( self ):
|
|
|
|
log.debug('========== processPO( )')
|
|
|
|
po_dir = os.path.join(self.build_root, "po")
|
|
|
|
mo_dir = os.path.join(self.build_src, "lang")
|
|
|
|
if not os.path.exists(mo_dir):
|
|
|
|
os.makedirs(mo_dir)
|
|
|
|
#TODO: find a better way to handle different platforms
|
|
|
|
if sys.platform == 'win32':
|
2018-09-04 07:33:17 +05:30
|
|
|
po_files = glob.glob(po_dir + r"\*.po")
|
2010-04-21 03:18:32 +05:30
|
|
|
# no longer using python msgfmt as it doesn't handle plurals (april 2010)
|
|
|
|
# msgfmtCmd = path.normpath(path.join(sys.prefix, "Tools/i18n/msgfmt.py") )
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
# GetText Win 32 obtained from http://gnuwin32.sourceforge.net/packages/gettext.htm
|
|
|
|
# ....\gettext\bin\msgfmt.exe needs to be on the path
|
|
|
|
msgfmtCmd = 'msgfmt.exe'
|
2016-08-22 20:18:17 +05:30
|
|
|
#print('msgfmtCmd = %s' % msgfmtCmd)
|
2010-04-21 03:18:32 +05:30
|
|
|
elif sys.platform == 'linux2':
|
|
|
|
po_files = glob.glob(po_dir + "/*.po")
|
|
|
|
msgfmtCmd = "%s/bin/msgfmt" % sys.prefix
|
|
|
|
else:
|
|
|
|
po_files = [] #empty list
|
|
|
|
msgfmtCmd = "UNKNOWN_PLATFORM"
|
|
|
|
log.debug( msgfmtCmd )
|
|
|
|
#if not os.path.exists(msgfmtCmd):
|
|
|
|
# log.error( "msgfmt not found - unable to generate mo files")
|
|
|
|
# return
|
|
|
|
log.info( "Generating mo files" )
|
2016-09-01 10:22:45 +05:30
|
|
|
global po_errs, po_oks
|
2010-04-21 03:18:32 +05:30
|
|
|
po_total = len(po_files)
|
2016-09-01 10:22:45 +05:30
|
|
|
po_count = 0
|
2010-04-21 03:18:32 +05:30
|
|
|
for po_file in po_files:
|
|
|
|
po_count = po_count + 1
|
|
|
|
#This will be interesting
|
|
|
|
self.emit("build_progresstext", 'compiling %s' % po_file)
|
|
|
|
self.emit("build_progressfraction", po_count/po_total)
|
|
|
|
|
|
|
|
lan = os.path.basename(po_file).replace( ".po", "" )
|
|
|
|
lan_path = os.path.join(mo_dir,lan,"LC_MESSAGES")
|
|
|
|
if not os.path.exists(lan_path):
|
|
|
|
os.makedirs(lan_path)
|
|
|
|
mo_file = os.path.join(lan_path,"gramps.mo")
|
|
|
|
log.info( mo_file )
|
|
|
|
|
2012-05-31 19:57:28 +05:30
|
|
|
cmd = [msgfmtCmd, '--statistics','-o', mo_file, po_file]
|
|
|
|
log.debug( cmd )
|
|
|
|
|
|
|
|
proc = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
|
|
|
log.info( output )
|
2010-04-21 03:18:32 +05:30
|
|
|
# log.debug( output ) Nothing coming out here, statistics come out stderr ??
|
|
|
|
if err:
|
|
|
|
log.info(err) # statistics comming out stderr
|
|
|
|
po_errs.append(lan)
|
|
|
|
else:
|
|
|
|
po_oks.append(lan)
|
|
|
|
|
|
|
|
def generateConstPy(self ):
|
|
|
|
log.debug('========== generate_const.py()')
|
|
|
|
fin = open(os.path.join(self.build_src,'const.py.in'), 'r')
|
|
|
|
in_lines = fin.readlines()
|
|
|
|
fin.close()
|
|
|
|
fout = open(os.path.join(self.build_src,'const.py'), 'w')
|
|
|
|
for line in in_lines:
|
|
|
|
if '@VERSIONSTRING@' in line: #VERSION = "@VERSIONSTRING@"
|
|
|
|
corrline = line.replace('@VERSIONSTRING@', self.gramps_version.replace(FULL_COLON_SUBST,":") )
|
|
|
|
fout.write(corrline)
|
|
|
|
#fout.write('VERSION = "%s"\n'% self.gramps_version.replace(FULL_COLON_SUBST,":"))
|
|
|
|
|
|
|
|
#elif '@prefix@' in line: #PREFIXDIR = "@prefix@"
|
|
|
|
# what to do? , doesnt seem to matter on windows
|
|
|
|
|
|
|
|
#elif '@sysconfdir@' in line: #SYSCONFDIR = "@sysconfdir@"
|
|
|
|
# what to do? , doesnt seem to matter on windows
|
|
|
|
|
|
|
|
else:
|
|
|
|
fout.write(line)
|
|
|
|
fout.close()
|
|
|
|
|
|
|
|
def cleanBuildDir(self):
|
|
|
|
log.debug( '========== cleanBuildDir()' )
|
|
|
|
log.info( 'Cleaning build and output directories' )
|
|
|
|
if sys.platform == 'win32': #both platforms emit different exceptions for the same operation, map the exception here
|
|
|
|
MY_EXCEPTION = WindowsError
|
|
|
|
elif sys.platform == 'linux2':
|
|
|
|
MY_EXCEPTION = OSError
|
|
|
|
if os.path.exists(self.build_root):
|
|
|
|
try:
|
|
|
|
log.info('removing directory: %s' % self.build_root )
|
|
|
|
shutil.rmtree(self.build_root)
|
2016-08-22 20:18:17 +05:30
|
|
|
except MY_EXCEPTION as e:
|
2010-04-21 03:18:32 +05:30
|
|
|
log.error( e )
|
|
|
|
|
|
|
|
for file in ['gramps-%s.exe'%self.gramps_version ]: #, 'build.log']:
|
|
|
|
fname = os.path.join(self.out_dir, file)
|
|
|
|
if os.path.isfile(fname):
|
|
|
|
try:
|
|
|
|
log.info('removing file: %s' % fname )
|
|
|
|
os.remove(fname)
|
2016-08-22 20:18:17 +05:30
|
|
|
except MY_EXCEPTION as e:
|
2010-04-21 03:18:32 +05:30
|
|
|
log.error( e )
|
|
|
|
|
|
|
|
def getNSISVersionNumber(self):
|
2016-09-01 10:22:45 +05:30
|
|
|
#Check version of NSIS, to ensure NSIS is compatible with script features
|
2010-04-21 03:18:32 +05:30
|
|
|
# >"c:\Program Files\NSIS\makensis.exe" /version
|
|
|
|
# v2.42
|
|
|
|
cmd = '"%s" -VERSION' % (MAKENSIS_exe)
|
|
|
|
log.debug(cmd)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
proc = subprocess.Popen( cmd, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
|
|
|
log.info( output )
|
2010-04-21 03:18:32 +05:30
|
|
|
if err:
|
|
|
|
log.error(err)
|
|
|
|
if sys.platform == 'win32': #'not recognized' in err:
|
|
|
|
minor =0
|
|
|
|
major =0
|
|
|
|
return (major, minor)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
#parse the output to get version number into tuple
|
|
|
|
ver = output[1:].split('.')
|
|
|
|
major = int(ver[0])
|
|
|
|
try:
|
2016-09-01 10:22:45 +05:30
|
|
|
minor = int(ver[1])
|
2016-08-22 20:18:17 +05:30
|
|
|
except ValueError as e:
|
2010-04-21 03:18:32 +05:30
|
|
|
m = ver[1]
|
2016-08-22 20:18:17 +05:30
|
|
|
minor = int(m[:2])
|
2010-04-21 03:18:32 +05:30
|
|
|
return (major, minor)
|
|
|
|
|
|
|
|
def checkForBuildTools(self):
|
|
|
|
global MAKENSIS_exe, SVN_exe
|
|
|
|
log.debug( '========== checkForBuildTools()' )
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
import _winreg as winreg
|
|
|
|
# Find NSIS on system
|
|
|
|
try:
|
|
|
|
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\NSIS') as key:
|
|
|
|
nsispath = winreg.QueryValue(key, '')
|
|
|
|
makensisexe = path.join( nsispath, 'makensis.exe')
|
|
|
|
if path.isfile( makensisexe ):
|
|
|
|
MAKENSIS_exe = makensisexe
|
2016-08-22 20:18:17 +05:30
|
|
|
except WindowsError as e:
|
2010-04-21 03:18:32 +05:30
|
|
|
log.warning('NSIS not found, in registory')
|
|
|
|
log.warning('..Testing if makensis is on the path')
|
|
|
|
MAKENSIS_exe = 'makensis'
|
|
|
|
#cmd = os.path.join(nsis_dir, MAKENSIS_exe)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
cmd = '%s /VERSION' % MAKENSIS_exe
|
|
|
|
proc = subprocess.Popen( cmd, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
|
|
|
log.info( output )
|
2010-04-21 03:18:32 +05:30
|
|
|
if err:
|
|
|
|
log.error(err)
|
|
|
|
log.error('....makensis.exe not found on path')
|
|
|
|
sys.exit(0)
|
|
|
|
#else:
|
|
|
|
# log.info("makensis version %s" % output)
|
|
|
|
|
|
|
|
# Find msgfmt on system
|
|
|
|
cmd = os.path.join(msg_dir, 'msgfmt.exe')
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
proc = subprocess.Popen( cmd, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
2012-05-31 10:05:23 +05:30
|
|
|
(out, err) = proc.communicate()
|
|
|
|
output = string.strip(out)
|
|
|
|
log.info( output )
|
2010-04-21 03:18:32 +05:30
|
|
|
if not err.startswith(cmd):
|
|
|
|
#log.error(err)
|
|
|
|
log.error('msgfmt.exe not found on path')
|
|
|
|
log.error(' try the -m DIR , --msgdir=DIR option to specify the directory or put it on the path')
|
|
|
|
sys.exit(0)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
# Find SVN on system - optional, if building from tarball
|
|
|
|
if not bTarball:
|
|
|
|
try:
|
|
|
|
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\svn.exe') as key:
|
|
|
|
svnpath = winreg.QueryValue(key, '')
|
|
|
|
if path.isfile(svnpath):
|
|
|
|
SVN_exe = svnpath
|
2016-08-22 20:18:17 +05:30
|
|
|
except WindowsError as e:
|
2010-04-21 03:18:32 +05:30
|
|
|
log.warning('SVN not found, in registory')
|
|
|
|
log.warning('... Hoping svn is on the path')
|
|
|
|
SVN_exe = 'svn'
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
elif sys.platform == 'linux2':
|
|
|
|
#ASSUMPTION: these tools are on the path
|
|
|
|
#TODO: check for svn on Linux
|
|
|
|
log.info( 'TODO: Check for svn' )
|
|
|
|
SVN_exe = 'svn'
|
|
|
|
#TODO: check for nsis on Linux
|
|
|
|
log.info( 'TODO: Check for nsis' )
|
|
|
|
MAKENSIS_exe = 'makensis'
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
# Check if we are running a compatible vesion of NSIS
|
|
|
|
vers = self.getNSISVersionNumber()
|
|
|
|
if vers < MIN_NSIS_VERSION:
|
|
|
|
log.error( "Require NSIS version %d.%d or later ..... found NSIS version %d.%d" % (MIN_NSIS_VERSION[0],MIN_NSIS_VERSION[1], vers[0], vers[1]) )
|
|
|
|
log.info("Disabling NSIS compilation ... Please upgrade your NSIS version")
|
|
|
|
self.bBuildInstaller = False
|
|
|
|
else:
|
|
|
|
self.bBuildInstaller = True
|
|
|
|
log.info( "NSIS version %d.%d" % vers )
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
def expandTarBall(self, tarball, expand_dir):
|
|
|
|
# gramps-3.1.0.tar.gz
|
|
|
|
log.info( 'expandTarBall(%s, %s)' % (tarball, expand_dir) )
|
|
|
|
if tarfile.is_tarfile(self.repository_path):
|
|
|
|
tar = tarfile.open(self.repository_path)
|
|
|
|
tar.extractall(self.out_dir)
|
|
|
|
tar.close()
|
2012-05-31 06:43:28 +05:30
|
|
|
#base = os.path.basename(self.repository_path)
|
|
|
|
extractDir = os.path.join(self.out_dir, self.tarbase3 )
|
2010-04-21 03:18:32 +05:30
|
|
|
try:
|
|
|
|
os.rename( extractDir, self.build_root)
|
2016-08-22 20:18:17 +05:30
|
|
|
except WindowsError as e:
|
2012-05-31 06:43:28 +05:30
|
|
|
log.error("FAILED: \n\t extractDir=%s \n\t build_root=%s" % (extractDir, self.build_root))
|
2016-08-22 20:18:17 +05:30
|
|
|
raise WindowsError(e)
|
2010-04-21 03:18:32 +05:30
|
|
|
else:
|
|
|
|
log.error( "Sorry %s is not a tar file" % self.repository_path )
|
|
|
|
|
|
|
|
def getVersionFromTarBall(self, tarball):
|
|
|
|
log.debug( 'getVersionFromTarBall(%s)' % (tarball))
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
if tarfile.is_tarfile(self.repository_path):
|
|
|
|
tar = tarfile.open(self.repository_path)
|
|
|
|
members = tar.getnames()
|
|
|
|
for member in members:
|
|
|
|
if 'configure.in' in member:
|
|
|
|
log.debug('Reading version from: %s' % member)
|
|
|
|
file = tar.extractfile(member)
|
|
|
|
lines = file.readlines()
|
|
|
|
vers = self.getVersionFromLines(lines)
|
2012-05-31 06:43:28 +05:30
|
|
|
if 'TODO' in member: #need to get path this will extract too, grab it of one of the files
|
|
|
|
self.tarbase3, rest = member.split('/', 1)
|
2016-08-22 20:18:17 +05:30
|
|
|
print('==ExtractPath', self.tarbase3)
|
2010-04-21 03:18:32 +05:30
|
|
|
tar.close()
|
|
|
|
log.debug( 'Version (%s)' % (vers) )
|
|
|
|
return vers
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-05-07 16:33:48 +05:30
|
|
|
def copyPatchTreeToDest(self, src, dst):
|
|
|
|
'''Patch a tarball build with alternate files as required.
|
|
|
|
At this stage do not allow new directories to be made or
|
|
|
|
new files to be added, just replace existing files.
|
|
|
|
'''
|
|
|
|
log.info('Patching: now in %s', src)
|
|
|
|
names = os.listdir(src)
|
|
|
|
#os.makedirs(dst) - not creating new dir
|
|
|
|
errors = []
|
|
|
|
for name in names:
|
|
|
|
srcname = os.path.join(src, name)
|
|
|
|
dstname = os.path.join(dst, name)
|
|
|
|
try:
|
|
|
|
if os.path.isfile(srcname) and os.path.isfile(dstname):
|
|
|
|
log.info('Overwriting %s -> %s' % (srcname, dstname))
|
|
|
|
shutil.copyfile(srcname, dstname)
|
|
|
|
elif os.path.isdir(srcname) and os.path.isdir(dstname):
|
|
|
|
self.copyPatchTreeToDest(srcname, dstname)
|
|
|
|
else:
|
|
|
|
log.error('UNDEFINED: %s -> %s' % (srcname, dstname))
|
2016-08-22 20:18:17 +05:30
|
|
|
except (IOError, os.error) as why:
|
2010-05-07 16:33:48 +05:30
|
|
|
errors.append((srcname, dstname, str(why)))
|
|
|
|
# catch the Error from the recursive copytree so that we can
|
|
|
|
# continue with other files
|
2016-08-22 20:18:17 +05:30
|
|
|
except Error as err:
|
2010-05-07 16:33:48 +05:30
|
|
|
errors.extend(err.args[0])
|
|
|
|
if errors:
|
|
|
|
raise Error(errors)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
def buildGRAMPS( base, out_dir, bTarball):
|
|
|
|
bo = buildbase()
|
|
|
|
|
|
|
|
bo.repository_path = base
|
|
|
|
bo.out_dir = out_dir
|
|
|
|
bo.bTarball = bTarball
|
|
|
|
bo.bBuildInstaller = bBuildInstaller
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
if not bo.bTarball and not bo.isGrampsRoot(bo.repository_path):
|
|
|
|
log.error( '$$$$ BAD Gramps Root specified $$$$')
|
|
|
|
else:
|
|
|
|
bo.checkForBuildTools()
|
|
|
|
if bo.bTarball:
|
|
|
|
bo.gramps_version = bo.getVersionFromTarBall( bo.repository_path )
|
|
|
|
bo.build_root = path.normpath(os.path.join(bo.out_dir, 'gramps-%s' % bo.gramps_version))
|
|
|
|
if bBuildAll:
|
|
|
|
bo.cleanBuildDir()
|
|
|
|
bo.expandTarBall(base, bo.out_dir)
|
|
|
|
bo.copyExtraFilesToBuildDir(bo.build_root )
|
|
|
|
else: #SVN Build
|
|
|
|
bo.gramps_version = bo.getVersionFromConfigureIn( base )
|
|
|
|
bo.build_root = path.normpath(os.path.join(bo.out_dir, 'gramps-%s' % bo.gramps_version))
|
|
|
|
if bBuildAll:
|
|
|
|
bo.cleanBuildDir()
|
|
|
|
os.mkdir(bo.build_root)
|
|
|
|
bo.exportSVN(os.path.join(base, 'src'), os.path.join(bo.build_root, 'src') )
|
|
|
|
bo.exportSVN(os.path.join(base, 'po'), os.path.join(bo.build_root, 'po') )
|
|
|
|
bo.exportSVN(os.path.join(base, 'example'), os.path.join(bo.build_root, 'examples') )
|
2016-09-01 10:22:45 +05:30
|
|
|
bo.generateConstPy( )
|
2010-04-21 03:18:32 +05:30
|
|
|
bo.copyExtraFilesToBuildDir(base)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-05-07 16:33:48 +05:30
|
|
|
if bPatchBuild:
|
|
|
|
bo.copyPatchTreeToDest( patch_dir, bo.build_root )
|
2010-04-21 03:18:32 +05:30
|
|
|
if bBuildAll:
|
|
|
|
bo.processPO( )
|
|
|
|
if bo.bBuildInstaller:
|
|
|
|
bo.compileInstallScript()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import getopt
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import tarfile
|
|
|
|
|
|
|
|
usage = '''Create Gramps Windows Installer.
|
|
|
|
Usage:
|
|
|
|
python build_GrampsWin32.py [options] [repository_path]
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
repository_path Path to the repository to build GRAMPS from, this can be either
|
|
|
|
- The root path of a SVN working copy
|
|
|
|
- A tarball that has been saved on local disk
|
|
|
|
- Left blank to build the SVN working copy this file is part of
|
|
|
|
Options:
|
|
|
|
-h, --help This help message.
|
|
|
|
-oDIR, --out=DIR Directory to build files (optional)
|
|
|
|
--nsis_only Build NSIS only (does not Clean & Build All)
|
|
|
|
-t --tarball Build release version from Tarball.
|
|
|
|
-mDIR, --msgdir=DIR Directory to msgfmt.exe
|
2010-05-07 16:33:48 +05:30
|
|
|
-pDIR, --patch=DIR Specify a directory to patch files into the build.
|
|
|
|
only valid for a tarball build.
|
2016-09-01 10:22:45 +05:30
|
|
|
This directory will allow you to patch the release after expanding
|
2010-05-07 16:33:48 +05:30
|
|
|
from tarball and before creating installer.
|
2016-09-01 10:22:45 +05:30
|
|
|
(n.b. each file to be replaced needs to be specified with full path
|
2010-05-07 16:33:48 +05:30
|
|
|
to exactly mimic the paths in the expanded tarball)
|
2010-04-21 03:18:32 +05:30
|
|
|
'''
|
|
|
|
# TODO: nsis_dir option - a path to nsismake (for occasions script cannot work it out)
|
|
|
|
# TODO: svn_dir option - a path to svn (for occasions script cannot work it out)
|
|
|
|
# TODO: tortoise_dir Option - accommodate windows user who dont have svn but use tortoiseSVN
|
|
|
|
|
|
|
|
repository_path = '.' # Repository - either SVN working copy dir or Tarball file
|
|
|
|
out_dir = None
|
|
|
|
bBuildAll = True
|
|
|
|
bBuildInstaller = True
|
|
|
|
bTarball = False
|
|
|
|
msg_dir = ""
|
2010-05-07 16:33:48 +05:30
|
|
|
bPatchBuild = False
|
|
|
|
patch_dir = ""
|
2010-04-21 03:18:32 +05:30
|
|
|
try:
|
2010-05-07 16:33:48 +05:30
|
|
|
opts, args = getopt.getopt(sys.argv[1:], "ho:tm:p:",
|
|
|
|
["help", "out=", "nsis_only", "tarball", "msgdir=", "patch="])
|
2010-04-21 03:18:32 +05:30
|
|
|
|
|
|
|
for o, a in opts:
|
|
|
|
if o in ("-h", "--help"):
|
2016-08-22 20:18:17 +05:30
|
|
|
print(usage)
|
2010-04-21 03:18:32 +05:30
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
if o in ("-o", "--out"):
|
|
|
|
out_dir = a
|
|
|
|
if o in ("--nsis_only"):
|
|
|
|
bBuildAll = False
|
|
|
|
if o in ('-t', "--tarball"):
|
2016-08-22 20:18:17 +05:30
|
|
|
print('This is a tarball build')
|
2010-04-21 03:18:32 +05:30
|
|
|
bTarball = True
|
|
|
|
if o in ("-m", "--msgdir"):
|
|
|
|
if os.path.isdir( a ):
|
|
|
|
msg_dir = a
|
|
|
|
else:
|
2016-08-22 20:18:17 +05:30
|
|
|
raise getopt.GetoptError('\nERROR: msgfmt dir does not exist')
|
2010-05-07 16:33:48 +05:30
|
|
|
if o in ("-p", "--patch"):
|
|
|
|
if os.path.isdir( a ):
|
|
|
|
patch_dir = a
|
|
|
|
bPatchBuild = True
|
|
|
|
else:
|
2016-08-22 20:18:17 +05:30
|
|
|
raise getopt.GetoptError('\nERROR: Patch directory does not exist')
|
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
if args: #got args use first one as base dir
|
|
|
|
repository_path = path.normpath(args[0])
|
|
|
|
else: # no base dir passed in, work out one from current working dir
|
|
|
|
repository_path = path.normpath("%s/../.." % os.getcwd() )
|
|
|
|
|
2010-05-07 16:33:48 +05:30
|
|
|
if bPatchBuild and not bTarball:
|
|
|
|
log.warning("Cannot specify patch for SVN build, resetting patch option")
|
|
|
|
patch_dir = None
|
2010-04-21 03:18:32 +05:30
|
|
|
# raise getopt.GetoptError, '\nERROR: No base directory specified'
|
|
|
|
|
|
|
|
if len(args) > 1:
|
2016-08-22 20:18:17 +05:30
|
|
|
raise getopt.GetoptError('\nERROR: Too many arguments')
|
2010-04-21 03:18:32 +05:30
|
|
|
|
2016-08-22 20:18:17 +05:30
|
|
|
except getopt.GetoptError as msg:
|
|
|
|
print(msg)
|
|
|
|
print('\n %s' % usage)
|
2010-04-21 03:18:32 +05:30
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
if bTarball:
|
|
|
|
if not tarfile.is_tarfile(repository_path):
|
2016-08-22 20:18:17 +05:30
|
|
|
print("Tarball %s not a valid Tarball" % repository_path)
|
2010-04-21 03:18:32 +05:30
|
|
|
sys.exit(1)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
|
|
|
else:
|
2010-04-21 03:18:32 +05:30
|
|
|
if not os.path.isdir(repository_path):
|
2016-08-22 20:18:17 +05:30
|
|
|
print("WC root directory not found; %s " % repository_path)
|
2010-04-21 03:18:32 +05:30
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if out_dir == None:
|
|
|
|
if bTarball:
|
|
|
|
out_dir = path.normpath(os.getcwd())
|
|
|
|
else:
|
|
|
|
out_dir = path.normpath(os.path.join(repository_path, 'windows'))
|
|
|
|
log.info("Setting outdir to %s", out_dir)
|
2016-08-22 20:18:17 +05:30
|
|
|
|
2010-04-21 03:18:32 +05:30
|
|
|
|
|
|
|
s_args = ''
|
|
|
|
for value in sys.argv[1:]:
|
|
|
|
s_args = s_args + ' %s'%value
|
|
|
|
|
2016-08-22 20:18:17 +05:30
|
|
|
print("======= build_GrampsWin32.py %s ========" % s_args)
|
2010-04-21 03:18:32 +05:30
|
|
|
log.debug('Using %s to find python tools' % sys.prefix)
|
|
|
|
log.info('Platform: %s' % sys.platform)
|
|
|
|
#==========================
|
|
|
|
sys.exit(buildGRAMPS(repository_path,out_dir, bTarball))
|
|
|
|
|
2016-09-01 10:22:45 +05:30
|
|
|
GObject.type_register(buildbase)
|