<commit_before>#
# Copyright (c) 2004 Specifix, Inc.
# All rights reserved
#
"""
Module used by recipes to direct the build and installation of
software packages.  Classes from this module are not used directly;
instead, they are used through eponymous interfaces in recipe.

@var _permmap: A mapping of common integer file modes to their octal
equivalents.  This is used to check for common mistakes when specifying
the permissions on files in classes derived from _PutFile.
"""

import os
import util
import fixedglob
import log

# make sure that the decimal value really is unreasonable before
# adding a new translation to this file.
_permmap = {
    1755: 01755,
    2755: 02755,
    4755: 04755,
    755: 0755,
    750: 0750,
    644: 0644,
    640: 0640,
}

class BuildAction(util.Action):
    keywords = {
        'use': None
    }

    def __init__(self, *args, **keywords):
	"""
	@keyword use: Optional argument; Use flag(s) telling whether
	to actually perform the action.
	@type use: None, Use flag, or sequence of Use flags
	"""
	# enforce pure virtual status
        assert(self.__class__ is not BuildCommand)
	util.Action.__init__(self, *args, **keywords)
	# change self.use to be a simple flag
	self.use = util.checkUse(self.use)

    def doBuild(self, recipe):
	self.recipe = recipe
	if self.use:
	    self.do(recipe.macros)

    def do(self, macros):
        """
        Do the build action

        @param macros: macro set to be used for expansion
        @type macros: recipe.Macros
        """
        raise AssertionError, "do method not implemented"


class BuildCommand(BuildAction, util.ShellCommand):
    """
    Pure virtual class which implements the do method,
    based on the shell command built from a template.
    """
    def __init__(self, *args, **keywords):
	# enforce pure virtual status
        assert(self.__class__ is not BuildCommand)
	BuildAction.__init__(self, *args, **keywords)
	util.ShellCommand.__init__(self, *args, **keywords)

    def do(self, macros):
        """
	Method which is used if the ShellCommand instance is invoked 
        during build
        @param macros: macros which will be expanded through dictionary
        substitution in self.command
        @type macros: recipe.Macros
        @return: None
        @rtype: None
	"""
        util.execute(self.command %macros)


class Run(BuildCommand):
    """
    Just run a command with simple macro substitution
    """
    template = "%(args)s"


class Automake(BuildCommand):
    # note: no use of %(args)s -- which command would it apply to?
    template = ('cd %%(builddir)s/%(subDir)s; '
                'aclocal %%(m4DirArgs)s %(acLocalArgs)s; '
		'%(preAutoconf)s autoconf %(autoConfArgs)s; '
		'automake%(automakeVer)s %(autoMakeArgs)s')
    keywords = {'autoConfArgs': '',
                'autoMakeArgs': '',
		'acLocalArgs': '',
		'preAutoconf': '',
                'm4Dir': '',
		'automakeVer': '',
                'subDir': ''}
    
    def do(self, macros):
	macros = macros.copy()
        if self.m4Dir:
	    macros.update({'m4DirArgs': '-I %s' %(self.m4Dir)})
        util.execute(self.command %macros)


class Configure(BuildCommand):
    """The Configure class runs an autoconf configure script with the
    default paths as defined by the macro set passed into it when doBuild
    is invoked.  It provides many common arguments, set correctly to
    values provided by system macros.  If any of these arguments do
    not work for a program, then use the ManualConfigure class instead.
    """
    # note that template is NOT a tuple, () is used merely to group strings
    # to avoid trailing \ characters on every line
    template = (
	'cd %%(builddir)s; '
	'%%(mkObjdir)s '
	'%%(cdSubDir)s '
	'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
	' %(preConfigure)s %%(configure)s'
	# XXX host/build/target here
	' --prefix=%%(prefix)s'
	' --exec-prefix=%%(exec_prefix)s'
	' --bindir=%%(bindir)s'
	' --sbindir=%%(sbindir)s'
	' --sysconfdir=%%(sysconfdir)s'
	' --datadir=%%(datadir)s'
	' --includedir=%%(includedir)s'
	' --libdir=%%(libdir)s'
	' --libexecdir=%%(libexecdir)s'
	' --localstatedir=%%(localstatedir)s'
	' --sharedstatedir=%%(sharedstatedir)s'
	' --mandir=%%(mandir)s'
	' --infodir=%%(infodir)s'
	'  %(args)s')
    keywords = {'preConfigure': '',
                'objDir': '',
		'subDir': ''}

    def __init__(self, *args, **keywords):
        """
        Create a new Configure instance used to run the autoconf configure
        command with default parameters

        @keyword objDir: make an object directory before running configure.
        This is useful for applications which do not support running configure
        from the same directory as the sources (srcdir != objdir)
	@keyword subDir: relative subdirectory in which to run configure
        @keyword preConfigure: Extra shell script which is inserted in front of
        the configure command.
        """
        BuildCommand.__init__(self, *args, **keywords)
         
    def do(self, macros):
	macros = macros.copy()
        if self.objDir:
            macros['mkObjdir'] = 'mkdir -p %s; cd %s;' \
	                         %(self.objDir, self.objDir)
	    macros['configure'] = '../configure'
        else:
            macros['configure'] = './configure'
	if self.subDir:
	    macros['cdSubDir'] = 'cd %s;' %self.subDir
        util.execute(self.command %macros)

class ManualConfigure(Configure):
    """
    The ManualConfigure class works exactly like the configure class,
    except that all the arguments to the configure script have to be
    provided explicitly.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
                '%%(mkObjdir)s '
	        '%(preConfigure)s %%(configure)s %(args)s')

class Make(BuildCommand):
    """
    The Make class runs the make utility with CFLAGS and CXXFLAGS set
    to system defaults, with system default for mflags and parallelmflags.
    This means, among other things, that if your package does not build
    correctly with parallelized make, you should disable parallel
    make by using self.disableParallelMake() in your recipe.  If your
    package can do parallel builds but needs some other mechanism,
    then you can modify parallelmflags as necessary in your recipe.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
	        'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
                ' %(preMake)s make %%(mflags)s %%(parallelmflags)s %(args)s')
    keywords = {'preMake': '',
                'subDir': ''}

    def __init__(self, *args, **keywords):
        """
        @keyword preMake: string to be inserted before the "make" command.
        Use preMake if you need to set an environment variable.  The
        preMake keyword cannot contain a ;
        @keyword subDir: the sub directory to enter before running "make"
        """
        if 'preMake' in keywords:
            if ';' in keywords['preMake']:
                raise TypeError, 'preMake argument cannot contain ;'
        BuildCommand.__init__(self, *args, **keywords)

class MakeParallelSubdir(Make):
    """
    The MakeParallelSubdir class runs the make utility with CFLAGS
    and CXXFLAGS set to system defaults, with system default for
    parallelmflags only applied to sub-make processes.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
	        'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
                ' %(preMake)s make %%(mflags)s '
                ' MAKE="make %%(mflags)s %%(parallelmflags)s" %(args)s')

class MakeInstall(Make):
    """
    The MakeInstall class is like the Make class, except that it
    automatically sets DESTDIR.  If your package does not have
    DESTDIR or an analog, use the MakePathsInstall class instead,
    or as a last option, the Make class.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
	        'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
                ' %(preMake)s make %%(mflags)s %%(rootVarArgs)s'
		' %(installtarget)s %(args)s')
    keywords = {'rootVar': 'DESTDIR',
		'installtarget': 'install'}

    def do(self, macros):
	macros = macros.copy()
        if self.rootVar:
	    macros.update({'rootVarArgs': '%s=%s'
	                  %(self.rootVar, macros['destdir'])})
	util.execute(self.command %macros)

class MakePathsInstall(Make):
    """
    The MakePathsInstall class is used when there is no single functional
    DESTDIR or similar definition, but enough of the de-facto standard 
    variables (prefix, bindir, etc) are honored by the Makefile to make
    a destdir installation successful.
    """
    template = (
	'cd %%(builddir)s/%(subDir)s; '
	'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
	' %(preMake)s make %%(mflags)s'
	' prefix=%%(destdir)s/%%(prefix)s'
	' exec-prefix=%%(destdir)s/%%(exec_prefix)s'
	' bindir=%%(destdir)s/%%(bindir)s'
	' sbindir=%%(destdir)s/%%(sbindir)s'
	' sysconfdir=%%(destdir)s/%%(sysconfdir)s'
	' datadir=%%(destdir)s/%%(datadir)s'
	' includedir=%%(destdir)s/%%(includedir)s'
	' libdir=%%(destdir)s/%%(libdir)s'
	' libexecdir=%%(destdir)s/%%(libexecdir)s'
	' localstatedir=%%(destdir)s/%%(localstatedir)s'
	' sharedstatedir=%%(destdir)s/%%(sharedstatedir)s'
	' mandir=%%(destdir)s/%%(mandir)s'
	' infodir=%%(destdir)s/%%(infodir)s'
	' %(installtarget)s %(args)s')
    keywords = {'installtarget': 'install'}


class _FileAction(BuildAction):
    keywords = {'component': None}

    def chmod(self, destdir, path):
	if self.mode >= 0:
            # fixup obviously broken permissions
	    if _permmap.has_key(self.mode):
                log.warning('odd permission %o, correcting to %o: add initial "0"?' \
                            %(self.mode, _permmap[self.mode]))
		self.mode = _permmap[self.mode]
	    os.chmod(destdir+os.sep+path, self.mode & 01777)
	    if self.mode & 06000:
		self.recipe.AddModes(self.mode, path)

    def setComponents(self, paths):
	"""
	XXX fixme
	A component without a : or with a leading : is relative to the main package name.
	A component with a trailing : is equivalent to having appended 'doc'
	"""
	if type(paths) is str:
	    paths = (paths,)
	for path in paths:
	    package = None
	    component = None
	    if self.component:
		if self.component.find(':') != -1:
		    (package, component) = self.component.split(':')
		else:
		    component = self.component
	    path = util.normpath(path)
	    if component:
		self.recipe.ComponentSpec(component, path)
	    if package:
		self.recipe.PackageSpec(package, path)
	

class InstallDesktopfile(BuildCommand, _FileAction):
    """
    The InstallDesktopfile class should be used to provide categories
    (and vendor, if necessary) for files in /usr/share/applications/
    """
    template = ('desktop-file-install --vendor %(vendor)s'<commit_msg>print warning for invalide desktop files<commit_after>#
# Copyright (c) 2004 Specifix, Inc.
# All rights reserved
#
"""
Module used by recipes to direct the build and installation of
software packages.  Classes from this module are not used directly;
instead, they are used through eponymous interfaces in recipe.

@var _permmap: A mapping of common integer file modes to their octal
equivalents.  This is used to check for common mistakes when specifying
the permissions on files in classes derived from _PutFile.
"""

import os
import util
import fixedglob
import log

# make sure that the decimal value really is unreasonable before
# adding a new translation to this file.
_permmap = {
    1755: 01755,
    2755: 02755,
    4755: 04755,
    755: 0755,
    750: 0750,
    644: 0644,
    640: 0640,
}

class BuildAction(util.Action):
    keywords = {
        'use': None
    }

    def __init__(self, *args, **keywords):
	"""
	@keyword use: Optional argument; Use flag(s) telling whether
	to actually perform the action.
	@type use: None, Use flag, or sequence of Use flags
	"""
	# enforce pure virtual status
        assert(self.__class__ is not BuildCommand)
	util.Action.__init__(self, *args, **keywords)
	# change self.use to be a simple flag
	self.use = util.checkUse(self.use)

    def doBuild(self, recipe):
	self.recipe = recipe
	if self.use:
	    self.do(recipe.macros)

    def do(self, macros):
        """
        Do the build action

        @param macros: macro set to be used for expansion
        @type macros: recipe.Macros
        """
        raise AssertionError, "do method not implemented"


class BuildCommand(BuildAction, util.ShellCommand):
    """
    Pure virtual class which implements the do method,
    based on the shell command built from a template.
    """
    def __init__(self, *args, **keywords):
	# enforce pure virtual status
        assert(self.__class__ is not BuildCommand)
	BuildAction.__init__(self, *args, **keywords)
	util.ShellCommand.__init__(self, *args, **keywords)

    def do(self, macros):
        """
	Method which is used if the ShellCommand instance is invoked 
        during build
        @param macros: macros which will be expanded through dictionary
        substitution in self.command
        @type macros: recipe.Macros
        @return: None
        @rtype: None
	"""
        util.execute(self.command %macros)


class Run(BuildCommand):
    """
    Just run a command with simple macro substitution
    """
    template = "%(args)s"


class Automake(BuildCommand):
    # note: no use of %(args)s -- which command would it apply to?
    template = ('cd %%(builddir)s/%(subDir)s; '
                'aclocal %%(m4DirArgs)s %(acLocalArgs)s; '
		'%(preAutoconf)s autoconf %(autoConfArgs)s; '
		'automake%(automakeVer)s %(autoMakeArgs)s')
    keywords = {'autoConfArgs': '',
                'autoMakeArgs': '',
		'acLocalArgs': '',
		'preAutoconf': '',
                'm4Dir': '',
		'automakeVer': '',
                'subDir': ''}
    
    def do(self, macros):
	macros = macros.copy()
        if self.m4Dir:
	    macros.update({'m4DirArgs': '-I %s' %(self.m4Dir)})
        util.execute(self.command %macros)


class Configure(BuildCommand):
    """The Configure class runs an autoconf configure script with the
    default paths as defined by the macro set passed into it when doBuild
    is invoked.  It provides many common arguments, set correctly to
    values provided by system macros.  If any of these arguments do
    not work for a program, then use the ManualConfigure class instead.
    """
    # note that template is NOT a tuple, () is used merely to group strings
    # to avoid trailing \ characters on every line
    template = (
	'cd %%(builddir)s; '
	'%%(mkObjdir)s '
	'%%(cdSubDir)s '
	'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
	' %(preConfigure)s %%(configure)s'
	# XXX host/build/target here
	' --prefix=%%(prefix)s'
	' --exec-prefix=%%(exec_prefix)s'
	' --bindir=%%(bindir)s'
	' --sbindir=%%(sbindir)s'
	' --sysconfdir=%%(sysconfdir)s'
	' --datadir=%%(datadir)s'
	' --includedir=%%(includedir)s'
	' --libdir=%%(libdir)s'
	' --libexecdir=%%(libexecdir)s'
	' --localstatedir=%%(localstatedir)s'
	' --sharedstatedir=%%(sharedstatedir)s'
	' --mandir=%%(mandir)s'
	' --infodir=%%(infodir)s'
	'  %(args)s')
    keywords = {'preConfigure': '',
                'objDir': '',
		'subDir': ''}

    def __init__(self, *args, **keywords):
        """
        Create a new Configure instance used to run the autoconf configure
        command with default parameters

        @keyword objDir: make an object directory before running configure.
        This is useful for applications which do not support running configure
        from the same directory as the sources (srcdir != objdir)
	@keyword subDir: relative subdirectory in which to run configure
        @keyword preConfigure: Extra shell script which is inserted in front of
        the configure command.
        """
        BuildCommand.__init__(self, *args, **keywords)
         
    def do(self, macros):
	macros = macros.copy()
        if self.objDir:
            macros['mkObjdir'] = 'mkdir -p %s; cd %s;' \
	                         %(self.objDir, self.objDir)
	    macros['configure'] = '../configure'
        else:
            macros['configure'] = './configure'
	if self.subDir:
	    macros['cdSubDir'] = 'cd %s;' %self.subDir
        util.execute(self.command %macros)

class ManualConfigure(Configure):
    """
    The ManualConfigure class works exactly like the configure class,
    except that all the arguments to the configure script have to be
    provided explicitly.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
                '%%(mkObjdir)s '
	        '%(preConfigure)s %%(configure)s %(args)s')

class Make(BuildCommand):
    """
    The Make class runs the make utility with CFLAGS and CXXFLAGS set
    to system defaults, with system default for mflags and parallelmflags.
    This means, among other things, that if your package does not build
    correctly with parallelized make, you should disable parallel
    make by using self.disableParallelMake() in your recipe.  If your
    package can do parallel builds but needs some other mechanism,
    then you can modify parallelmflags as necessary in your recipe.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
	        'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
                ' %(preMake)s make %%(mflags)s %%(parallelmflags)s %(args)s')
    keywords = {'preMake': '',
                'subDir': ''}

    def __init__(self, *args, **keywords):
        """
        @keyword preMake: string to be inserted before the "make" command.
        Use preMake if you need to set an environment variable.  The
        preMake keyword cannot contain a ;
        @keyword subDir: the sub directory to enter before running "make"
        """
        if 'preMake' in keywords:
            if ';' in keywords['preMake']:
                raise TypeError, 'preMake argument cannot contain ;'
        BuildCommand.__init__(self, *args, **keywords)

class MakeParallelSubdir(Make):
    """
    The MakeParallelSubdir class runs the make utility with CFLAGS
    and CXXFLAGS set to system defaults, with system default for
    parallelmflags only applied to sub-make processes.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
	        'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
                ' %(preMake)s make %%(mflags)s '
                ' MAKE="make %%(mflags)s %%(parallelmflags)s" %(args)s')

class MakeInstall(Make):
    """
    The MakeInstall class is like the Make class, except that it
    automatically sets DESTDIR.  If your package does not have
    DESTDIR or an analog, use the MakePathsInstall class instead,
    or as a last option, the Make class.
    """
    template = ('cd %%(builddir)s/%(subDir)s; '
	        'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
                ' %(preMake)s make %%(mflags)s %%(rootVarArgs)s'
		' %(installtarget)s %(args)s')
    keywords = {'rootVar': 'DESTDIR',
		'installtarget': 'install'}

    def do(self, macros):
	macros = macros.copy()
        if self.rootVar:
	    macros.update({'rootVarArgs': '%s=%s'
	                  %(self.rootVar, macros['destdir'])})
	util.execute(self.command %macros)

class MakePathsInstall(Make):
    """
    The MakePathsInstall class is used when there is no single functional
    DESTDIR or similar definition, but enough of the de-facto standard 
    variables (prefix, bindir, etc) are honored by the Makefile to make
    a destdir installation successful.
    """
    template = (
	'cd %%(builddir)s/%(subDir)s; '
	'CFLAGS="%%(cflags)s" CXXFLAGS="%%(cflags)s"'
	' %(preMake)s make %%(mflags)s'
	' prefix=%%(destdir)s/%%(prefix)s'
	' exec-prefix=%%(destdir)s/%%(exec_prefix)s'
	' bindir=%%(destdir)s/%%(bindir)s'
	' sbindir=%%(destdir)s/%%(sbindir)s'
	' sysconfdir=%%(destdir)s/%%(sysconfdir)s'
	' datadir=%%(destdir)s/%%(datadir)s'
	' includedir=%%(destdir)s/%%(includedir)s'
	' libdir=%%(destdir)s/%%(libdir)s'
	' libexecdir=%%(destdir)s/%%(libexecdir)s'
	' localstatedir=%%(destdir)s/%%(localstatedir)s'
	' sharedstatedir=%%(destdir)s/%%(sharedstatedir)s'
	' mandir=%%(destdir)s/%%(mandir)s'
	' infodir=%%(destdir)s/%%(infodir)s'
	' %(installtarget)s %(args)s')
    keywords = {'installtarget': 'install'}


class _FileAction(BuildAction):
    keywords = {'component': None}

    def chmod(self, destdir, path):
	if self.mode >= 0:
            # fixup obviously broken permissions
	    if _permmap.has_key(self.mode):
                log.warning('odd permission %o, correcting to %o: add initial "0"?' \
                            %(self.mode, _permmap[self.mode]))
		self.mode = _permmap[self.mode]
	    os.chmod(destdir+os.sep+path, self.mode & 01777)
	    if self.mode & 06000:
		self.recipe.AddModes(self.mode, path)

    def setComponents(self, paths):
	"""
	XXX fixme
	A component without a : or with a leading : is relative to the main package name.
	A component with a trailing : is equivalent to having appended 'doc'
	"""
	if type(paths) is str:
	    paths = (paths,)
	for path in paths:
	    package = None
	    component = None
	    if self.component:
		if self.component.find(':') != -1:
		    (package, component) = self.component.split(':')
		else:
		    component = self.component
	    path = util.normpath(path)
	    if component:
		self.recipe.ComponentSpec(component, path)
	    if package:
		self.recipe.PackageSpec(package, path)
	

class InstallDesktopfile(BuildCommand, _FileAction):
    """
    The InstallDesktopfile class should be used to provide categories
    (and vendor, if necessary) for files in /usr/share/applications/
    """
    template = ('desktop-file-validate %(args)s; '
		'desktop-file-install --vendor %(vendor)s'
{'fraction_non_alphanumeric': 0.1306490608145806, 'fraction_numerical': 0.0071601264645713225, 'mean_word_length': 3.1008579599618686, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '566604', 'n_tokens_mistral': 7141, 'n_tokens_neox': 6740, 'n_words': 2030}