<commit_before>#
# Copyright (c) 2004-2006 rPath, Inc.
#
# All Rights Reserved
#

# python standard library imports
import errno
from math import ceil
import os
import sys
import re
import pwd
import time
import tempfile
import zipfile

# mint imports
from mint import mint_error
from mint import releasetypes
from mint.distro import gencslist
from mint.distro.imagegen import ImageGenerator, MSG_INTERVAL
from mint.client import upstream

# conary imports
from conary import conaryclient
from conary import flavorcfg
from conary import versions
from conary.callbacks import ChangesetCallback
from conary.conarycfg import ConfigFile, CfgDict, CfgString, CfgBool
from conary.callbacks import UpdateCallback
from conary.conaryclient.cmdline import parseTroveSpec
from conary.deps import deps
from conary.lib import log, util
from conary.repository import errors

PARTITION_OFFSET = 512

class KernelTroveRequired(mint_error.MintError):
    def __str__(self):
        return "Your group must include a kernel for proper operation."


class BootableImageConfig(ConfigFile):
    filename = 'bootable_image.conf'

    #Different cylinder sizes.  I don't know which is better, but I've seen
    #both: 8225280 or 516096
    cylindersize    = 516096
    sectors         = 63
    heads           = 16

    #directory containing the uml init script as well as fstab and other hooks
    dataDir         = '/usr/share/rbuilder/DiskImageData/'
    umlKernel       = CfgDict(CfgString)
    debug           = (CfgBool, 0)

    # where to look for tools needed to boot a live ISO.
    fallbackDir     = '/srv/rbuilder/fallback'
    toolkitImage     = '/srv/rbuilder/toolkit/image_maker.img'

class Journal:
    def lchown(self, root, target, user, group):
        # put UIDGID entries for directories on .
        if os.path.isdir(target) and not os.path.islink(target):
            target = target[len(root):]
            filename = '.'
            f = open(os.sep.join((root, target, '.UIDGID')), 'a')
        else:
            # get rid of the root
            target = target[len(root):]
            dirname = os.path.dirname(target)
            filename = os.path.basename(target)
            f = open(os.sep.join((root, dirname, '.UIDGID')), 'a')
        trfilename = filename.replace(' ', r'\ ').replace('\t', r'\t')
        f.write('%s %s %s\n' %(trfilename, user, group))
        f.close()

    def mknod(self, root, target, devtype, major, minor, mode,
              uid, gid):
        # get rid of the root
        target = target[len(root):]
        dirname = os.path.dirname(target)
        filename = os.path.basename(target)
        f = open(os.sep.join((root, dirname, '.DEVICES')), 'a')
        # XXX e2fsimage does not handle symbolic users/groups for .DEVICES
        # But this doesn't matter as .UIDGID is processed after .DEVICES
        trfilename = filename.replace(' ', r'\ ').replace('\t', r'\t')
        f.write('%s %s %d %d 0%o\n' %(trfilename, devtype, major, minor, mode))
        f.close()

def timeMe(func):
    def wrapper(self, *args, **kwargs):
        clock = time.clock()
        actual = time.time()
        returner = func(self, *args, **kwargs)
        log.info("%s: %.5f %.5f" % (func.__name__, time.clock() - clock, time.time() - actual))
        return returner
    return wrapper

def outputfilesize(func):
    def wrapper(self, *args, **kwargs):
        returner = func(self, *args, **kwargs)
        st = os.stat(self.outfile)
        log.debug("size of %s after %s: %d bytes" % (self.outfile, func.__name__, st.st_size))
        return returner
    return wrapper


class InstallCallback(UpdateCallback, ChangesetCallback):
    def restoreFiles(self, size, totalSize):
        if totalSize != 0:
            self.restored += size
            self.update('Writing files')

    def requestingChangeSet(self):
        self.update('Requesting changeset')

    def downloadingChangeSet(self, got, need):
        if need != 0:
            self.update('Downloading changeset')

    def requestingFileContents(self):
        self.update('Requesting file contents')

    def downloadingFileContents(self, got, need):
        if need != 0:
            self.update('Downloading files')

    def preparingChangeSet(self):
        self.update('Preparing changeset')

    def resolvingDependencies(self):
        self.update('Resolving dependencies')

    def creatingRollback(self):
        self.update('Creating rollback')

    def creatingDatabaseTransaction(self, troveNum, troveCount):
        self.update('Creating database transaction')

    def committingTransaction(self):
        self.update('Committing transaction')

    def setUpdateHunk(self, num, total):
        self.updateHunk = (num, total)
        self.restored = 0

    def update(self, msg):
        curTime = time.time()
        # only push an update into the database if it differs from the
        # current message
        if self.updateHunk[1] != 0:
            percent = (self.updateHunk[0] * 100) / self.updateHunk[1]
            msg = "Updating changesets: %d%% (%s)" % (percent, msg)

        if self.msg != msg and (curTime - self.timeStamp) > MSG_INTERVAL:
            self.msg = msg
            self.status(msg)
            self.timeStamp = curTime

    def __init__(self, status):
        self.abortEvent = None
        self.status = status
        self.restored = 0
        self.updateHunk = (0, 0)
        self.msg = ''
        self.changeset = ''
        self.prefix = 'BDI:'
        self.timeStamp = 0

class BootableImage(ImageGenerator):
    configObject = BootableImageConfig

    @outputfilesize
    @timeMe
    def prepareDiskImage(self):
        #create the disk file this will blank the file if it exists.
        ofile = open(self.outfile, 'wb', 0644)
        ofile.seek(self.imagesize-1)
        ofile.write('\x00')
        ofile.close()

        #Do the partition table
        self.cylinders = self.imagesize / self.imgcfg.cylindersize
        cmd = '/sbin/sfdisk -C %d -S %d -H %d %s' % (self.cylinders, self.imgcfg.sectors, self.imgcfg.heads, self.outfile)
        input = "0 %d L *\n" % self.cylinders

        if not self.imgcfg.debug:
            cmd += " >& /dev/null"
        sfdisk = util.popen(cmd, 'w')
        sfdisk.write(input)
        retval = sfdisk.close()

    def _writefstab(self):
        util.copyfile(os.path.join(self.imgcfg.dataDir, 'fstab'), os.path.join(self.fakeroot, 'etc'))
        if not self.swapSize:
            # remove any reference to swap if swapSize is 0
            util.execute('sed -i "s/.*swap.*//" %s' % \
                         os.path.join(self.fakeroot, 'etc', 'fstab'))

    def _setupGrub(self):
        if not os.path.exists(os.path.join(self.fakeroot, 'sbin', 'grub')):
            log.info("grub not found. skipping setup.")
            return
        util.copytree(os.path.join(self.fakeroot, 'usr', 'share', 'grub', '*', '*'), os.path.join(self.fakeroot, 'boot', 'grub'))
        #Create a stub grub.conf
        name = open(os.path.join(self.fakeroot, 'etc', 'issue'), 'r').readlines()[0].strip()
        # make initrd line in grub conf contingent on actually having one.
        macros = {'name': name, 'kversion': 'template', 'initrdCmd' : ''}
        bootDirFiles = os.listdir(os.path.join(self.fakeroot, 'boot'))
        if [x for x in bootDirFiles if re.match('initrd-.*.img', x)]:
            macros['initrdCmd'] = 'initrd /boot/initrd-%(kversion)s.img'
        # The following will allow xen domU images to run with pygrub and
        # use the kernel inside the image instead of relying on the dom0
        # to have a kernel installed.
        xen = False
        if [x for x in bootDirFiles if re.match('vmlinuz-.*xen.*', x)]:
            xen = True
        fd = open(os.path.join(self.fakeroot, 'boot', 'grub', 'grub.conf'), 'w')
        if xen:
            fd.write("""
#grub.conf generated by rBuilder
#
# Note that you do not have to rerun grub after making changes to this file
#boot=/dev/hda
default=0
timeout=0
title %(name)s (%(kversion)s)
    root (hd0,0)
    kernel /boot/vmlinuz-%(kversion)s ro root=LABEL=/ quiet
    %(initrdCmd)s
<commit_msg>don't depend on /etc/issue for distro name<commit_after>#
# Copyright (c) 2004-2006 rPath, Inc.
#
# All Rights Reserved
#

# python standard library imports
import errno
from math import ceil
import os
import sys
import re
import pwd
import time
import tempfile
import zipfile

# mint imports
from mint import mint_error
from mint import releasetypes
from mint.distro import gencslist
from mint.distro.imagegen import ImageGenerator, MSG_INTERVAL
from mint.client import upstream

# conary imports
from conary import conaryclient
from conary import flavorcfg
from conary import versions
from conary.callbacks import ChangesetCallback
from conary.conarycfg import ConfigFile, CfgDict, CfgString, CfgBool
from conary.callbacks import UpdateCallback
from conary.conaryclient.cmdline import parseTroveSpec
from conary.deps import deps
from conary.lib import log, util
from conary.repository import errors

PARTITION_OFFSET = 512

class KernelTroveRequired(mint_error.MintError):
    def __str__(self):
        return "Your group must include a kernel for proper operation."


class BootableImageConfig(ConfigFile):
    filename = 'bootable_image.conf'

    #Different cylinder sizes.  I don't know which is better, but I've seen
    #both: 8225280 or 516096
    cylindersize    = 516096
    sectors         = 63
    heads           = 16

    #directory containing the uml init script as well as fstab and other hooks
    dataDir         = '/usr/share/rbuilder/DiskImageData/'
    umlKernel       = CfgDict(CfgString)
    debug           = (CfgBool, 0)

    # where to look for tools needed to boot a live ISO.
    fallbackDir     = '/srv/rbuilder/fallback'
    toolkitImage     = '/srv/rbuilder/toolkit/image_maker.img'

class Journal:
    def lchown(self, root, target, user, group):
        # put UIDGID entries for directories on .
        if os.path.isdir(target) and not os.path.islink(target):
            target = target[len(root):]
            filename = '.'
            f = open(os.sep.join((root, target, '.UIDGID')), 'a')
        else:
            # get rid of the root
            target = target[len(root):]
            dirname = os.path.dirname(target)
            filename = os.path.basename(target)
            f = open(os.sep.join((root, dirname, '.UIDGID')), 'a')
        trfilename = filename.replace(' ', r'\ ').replace('\t', r'\t')
        f.write('%s %s %s\n' %(trfilename, user, group))
        f.close()

    def mknod(self, root, target, devtype, major, minor, mode,
              uid, gid):
        # get rid of the root
        target = target[len(root):]
        dirname = os.path.dirname(target)
        filename = os.path.basename(target)
        f = open(os.sep.join((root, dirname, '.DEVICES')), 'a')
        # XXX e2fsimage does not handle symbolic users/groups for .DEVICES
        # But this doesn't matter as .UIDGID is processed after .DEVICES
        trfilename = filename.replace(' ', r'\ ').replace('\t', r'\t')
        f.write('%s %s %d %d 0%o\n' %(trfilename, devtype, major, minor, mode))
        f.close()

def timeMe(func):
    def wrapper(self, *args, **kwargs):
        clock = time.clock()
        actual = time.time()
        returner = func(self, *args, **kwargs)
        log.info("%s: %.5f %.5f" % (func.__name__, time.clock() - clock, time.time() - actual))
        return returner
    return wrapper

def outputfilesize(func):
    def wrapper(self, *args, **kwargs):
        returner = func(self, *args, **kwargs)
        st = os.stat(self.outfile)
        log.debug("size of %s after %s: %d bytes" % (self.outfile, func.__name__, st.st_size))
        return returner
    return wrapper


class InstallCallback(UpdateCallback, ChangesetCallback):
    def restoreFiles(self, size, totalSize):
        if totalSize != 0:
            self.restored += size
            self.update('Writing files')

    def requestingChangeSet(self):
        self.update('Requesting changeset')

    def downloadingChangeSet(self, got, need):
        if need != 0:
            self.update('Downloading changeset')

    def requestingFileContents(self):
        self.update('Requesting file contents')

    def downloadingFileContents(self, got, need):
        if need != 0:
            self.update('Downloading files')

    def preparingChangeSet(self):
        self.update('Preparing changeset')

    def resolvingDependencies(self):
        self.update('Resolving dependencies')

    def creatingRollback(self):
        self.update('Creating rollback')

    def creatingDatabaseTransaction(self, troveNum, troveCount):
        self.update('Creating database transaction')

    def committingTransaction(self):
        self.update('Committing transaction')

    def setUpdateHunk(self, num, total):
        self.updateHunk = (num, total)
        self.restored = 0

    def update(self, msg):
        curTime = time.time()
        # only push an update into the database if it differs from the
        # current message
        if self.updateHunk[1] != 0:
            percent = (self.updateHunk[0] * 100) / self.updateHunk[1]
            msg = "Updating changesets: %d%% (%s)" % (percent, msg)

        if self.msg != msg and (curTime - self.timeStamp) > MSG_INTERVAL:
            self.msg = msg
            self.status(msg)
            self.timeStamp = curTime

    def __init__(self, status):
        self.abortEvent = None
        self.status = status
        self.restored = 0
        self.updateHunk = (0, 0)
        self.msg = ''
        self.changeset = ''
        self.prefix = 'BDI:'
        self.timeStamp = 0

class BootableImage(ImageGenerator):
    configObject = BootableImageConfig

    @outputfilesize
    @timeMe
    def prepareDiskImage(self):
        #create the disk file this will blank the file if it exists.
        ofile = open(self.outfile, 'wb', 0644)
        ofile.seek(self.imagesize-1)
        ofile.write('\x00')
        ofile.close()

        #Do the partition table
        self.cylinders = self.imagesize / self.imgcfg.cylindersize
        cmd = '/sbin/sfdisk -C %d -S %d -H %d %s' % (self.cylinders, self.imgcfg.sectors, self.imgcfg.heads, self.outfile)
        input = "0 %d L *\n" % self.cylinders

        if not self.imgcfg.debug:
            cmd += " >& /dev/null"
        sfdisk = util.popen(cmd, 'w')
        sfdisk.write(input)
        retval = sfdisk.close()

    def _writefstab(self):
        util.copyfile(os.path.join(self.imgcfg.dataDir, 'fstab'), os.path.join(self.fakeroot, 'etc'))
        if not self.swapSize:
            # remove any reference to swap if swapSize is 0
            util.execute('sed -i "s/.*swap.*//" %s' % \
                         os.path.join(self.fakeroot, 'etc', 'fstab'))

    def _setupGrub(self):
        if not os.path.exists(os.path.join(self.fakeroot, 'sbin', 'grub')):
            log.info("grub not found. skipping setup.")
            return
        util.copytree(os.path.join(self.fakeroot, 'usr', 'share', 'grub', '*', '*'), os.path.join(self.fakeroot, 'boot', 'grub'))
        #Create a stub grub.conf
        if os.path.exists(os.path.join(self.fakeroot, 'etc', 'issue')):
            name = open(os.path.join(self.fakeroot, 'etc', 'issue'), 'r').readlines()[0].strip()
        else:
            name = self.project.getName()
        # make initrd line in grub conf contingent on actually having one.
        macros = {'name': name, 'kversion': 'template', 'initrdCmd' : ''}
        bootDirFiles = os.listdir(os.path.join(self.fakeroot, 'boot'))
        if [x for x in bootDirFiles if re.match('initrd-.*.img', x)]:
            macros['initrdCmd'] = 'initrd /boot/initrd-%(kversion)s.img'
        # The following will allow xen domU images to run with pygrub and
        # use the kernel inside the image instead of relying on the dom0
        # to have a kernel installed.
        xen = False
        if [x for x in bootDirFiles if re.match('vmlinuz-.*xen.*', x)]:
            xen = True
        fd = open(os.path.join(self.fakeroot, 'boot', 'grub', 'grub.conf'), 'w')
        if xen:
            fd.write("""
#grub.conf generated by rBuilder
#
# Note that you do not have to rerun grub after making changes to this file
#boot=/dev/hda
default=0
timeout=0
title %(name)s (%(kversion)s)
    root (hd0,0)
    kernel /boot/vmlinuz-%(kversion)s ro root=LABEL=/ quiet
    %(initrdCmd)s

{'fraction_non_alphanumeric': 0.12102220870094312, 'fraction_numerical': 0.00839671432917554, 'mean_word_length': 2.5285530270502363, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '493779', 'n_tokens_mistral': 5279, 'n_tokens_neox': 5053, 'n_words': 1449}