-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Attached is the second version of the patch I posted yesterday. This version 
takes
into account comments offered by the list.

Jesse, I added tree copy code, but haven't heavily tested it yet. I will add a
release-test option today though.

Michael, this patch is essentially a 'git diff -p' of my stuff merged locally 
into
master, but with your changes to releasetests.sh, et al, removed (didn't want to
muddy the waters).

Clark
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iD8DBQFHYqcPHyuj/+TTEp0RAhdXAKDPS58hBlTw2U04gVuxemq7usBjAgCcDpzm
nduFWlb3+guUWWIekkcPbEg=
=kber
-----END PGP SIGNATURE-----
diff --git a/configure.ac b/configure.ac
index 99bca21..91407cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ AC_INIT([mock],[0.9.2])
 temp_RELEASE_NAME=mock
 temp_RELEASE_MAJOR=0
 temp_RELEASE_MINOR=9
-temp_RELEASE_SUBLEVEL=2
+temp_RELEASE_SUBLEVEL=3
 temp_RELEASE_EXTRALEVEL=
 
 ####################################
diff --git a/docs/mock.1 b/docs/mock.1
index ac295e6..4afde95 100644
--- a/docs/mock.1
+++ b/docs/mock.1
@@ -17,6 +17,10 @@ mock  [options] \fB\-\-install\fR PACKAGE
 mock  [options] \fB\-\-update\fR
 .LP
 mock  [options] \fB\-\-orphanskill\fR
+.LP
+mock  [options] \fB\-\-copyin\fR \fIpath [\fIpath...\fR] \fIdestination\fR
+.LP
+mock  [options] \fB\-\-copyout\fR \fIpath [\fIpath...\fR] \fIdestination\fR
 
 .SH "DESCRIPTION"
 .LP
@@ -97,24 +101,41 @@ Show version number and exit.
 .SH "COMMANDS"
 .LP
 .TP
-\fB\-\-clean\fR \- purge the chroot tree
+\fB\-\-clean\fP
+Purge the chroot tree
 .TP
-\fB\-\-init\fR \- initialize a chroot (clean, install chroot packages, etc.)
+\fB\-\-init\fP
+Initialize a chroot (clean, install chroot packages, etc.)
 .TP
-\fB\-\-rebuild\fR \- If no command is specified, rebuild is assumed. Rebuilds 
the specified SRPM(s). The buildroot is cleaned first, unless --no-clean is 
specified.
+\fB\-\-rebuild\fP
+If no command is specified, rebuild is assumed. Rebuilds the specified 
SRPM(s). The buildroot is cleaned first, unless --no-clean is specified.
 .TP
-\fB\-\-shell\fR \- run the specified command interactively within the chroot 
(which must already be initialized -- no 'clean' is performed). If no command 
specified, /bin/sh is run.
+\fB\-\-shell\fP
+Run the specified command interactively within the chroot (which must already 
be initialized -- no 'clean' is performed). If no command specified, /bin/sh is 
run.
 .TP
-\fB\-\-chroot\fR \- run the specified command non-interactively within the 
chroot (which must already be initialized -- no 'clean' is performed). Command 
output will be sent to the log files.
+\fB\-\-chroot\fP 
+Run the specified command non-interactively within the chroot (which must 
already be initialized -- no 'clean' is performed). Command output will be sent 
to the log files.
 .TP
-\fB\-\-installdeps\fR \- find out deps for SRPM or RPM, and do a yum install 
to put them in the buildroot. Buildroot must already be initialized -- no 
'clean' is performed
+\fB\-\-installdeps\fP 
+Find out deps for SRPM or RPM, and do a yum install to put them in the 
buildroot. Buildroot must already be initialized -- no 'clean' is performed
 .TP
-\fB\-\-install\fR \- Do a yum install PACKAGE inside the buildroot. Buildroot 
must already be initialized -- no 'clean' is performed
+\fB\-\-install\fP
+Do a yum install PACKAGE inside the buildroot. Buildroot must already be 
initialized -- no 'clean' is performed
 .TP
-\fB\-\-update\fR \- Do a yum update inside the buildroot. Buildroot must 
already be initialized -- no 'clean' is performed
+\fB\-\-update\fP 
+Do a yum update inside the buildroot. Buildroot must already be initialized -- 
no 'clean' is performed
 .TP
 \fB\-\-orphanskill\fP
 Noop mode that simply checks that no stray processes are running in the 
chroot. Kills any processes that it finds using specified root.
+.TP
+\fB\-\-copyin\fP
+Copies the source paths (files or directory trees) into the chroot at
+the specified destination path. 
+.TP
+\fB\-\-copyout\fP
+Copies the source paths (files or directory trees) from the chroot to
+the specified destination path. 
+
 .SH "FILES"
 .LP
 \fI/etc/mock/\fP \- default configuration directory
diff --git a/py/mock.py b/py/mock.py
index e7790f0..a560c89 100755
--- a/py/mock.py
+++ b/py/mock.py
@@ -25,6 +25,8 @@
            mock [options] {--shell|--chroot} <cmd>
            mock [options] --installdeps {SRPM|RPM}
            mock [options] --install PACKAGE
+           mock [options] --copyin path [..path] destination
+           mock [options] --copyout path [..path] destination
 """
 
 # library imports
@@ -65,6 +67,8 @@ import mock.util
 def command_parse(config_opts):
     """return options and args from parsing the command line"""
     parser = OptionParser(usage=__doc__, version=__VERSION__)
+
+    # modes (basic commands)
     parser.add_option("--rebuild", action="store_const", const="rebuild",
                       dest="mode", default='rebuild',
                       help="rebuild the specified SRPM(s)")
@@ -93,6 +97,15 @@ def command_parse(config_opts):
                       dest="mode",
                       help="Kill all processes using specified buildroot.")
 
+    parser.add_option("--copyin", action="store_const", const="copyin",
+                      dest="mode",
+                      help="Copy file(s) into the specified chroot")
+
+    parser.add_option("--copyout", action="store_const", const="copyout",
+                      dest="mode", 
+                      help="Copy file(s) from the specified chroot")
+    
+    # options
     parser.add_option("-r", action="store", type="string", dest="chroot",
                       help="chroot name/config file name default: %default",
                       default='default')
@@ -528,7 +541,45 @@ def main(ret):
 
     elif options.mode == 'orphanskill':
         mock.util.orphansKill(chroot.rootdir)
-
+    elif options.mode == 'copyin':
+        chroot.tryLockBuildRoot()
+        chroot._resetLogging()
+        uidManager.dropPrivsForever()
+        if len(args) < 2:
+            log.critical("Must have source and destinations for copyin")
+            sys.exit(50)
+        dest = chroot.makeChrootPath(args[-1])
+        if len(args) > 2 and not os.path.isdir(dest):
+            log.critical("multiple source files and %s is not a directory!" % 
dest)
+            sys.exit(50)
+        args = args[:-1]
+        import shutil
+        for src in args:
+            log.debug("copying %s to %s" % (src, dest))
+            if os.path.isdir(src):
+                shutil.copytree(src, dest)
+            else:
+                shutil.copy(src, dest)
+    elif options.mode == 'copyout':
+        chroot.tryLockBuildRoot()
+        chroot._resetLogging()
+        uidManager.dropPrivsForever()
+        if len(args) < 2:
+            log.critical("Must have source and destinations for copyout")
+            sys.exit(50)
+        dest = args[-1]
+        if len(args) > 2 and not os.path.isdir(dest):
+            log.critical("multiple source files and %s is not a directory!" % 
dest)
+            sys.exit(50)
+        args = args[:-1]
+        import shutil
+        for f in args:
+            src = chroot.makeChrootPath(f)
+            log.debug("copying %s to %s" % (src, dest))
+            if os.path.isdir(src):
+                shutil.copytree(src, dest)
+            else:
+                shutil.copy(src, dest)
 
 if __name__ == '__main__':
     # fix for python 2.4 logging module bug:
diff --git a/py/mock/backend.py b/py/mock/backend.py
index 4593357..c850118 100644
--- a/py/mock/backend.py
+++ b/py/mock/backend.py
@@ -142,6 +142,14 @@ class Root(object):
         return 1
 
     decorate(traceLog())
+    def makeChrootPath(self, *args):
+        '''For safety reasons, self.rootdir should not be used directly. 
Instead
+        use this handy helper function anytime you want to reference a path in
+        relation to the chroot.'''
+        tmp = self.rootdir + "/" + "/".join(args)
+        return tmp.replace("//", "/")
+
+    decorate(traceLog())
     def init(self):
         self.state("init")
 
@@ -188,41 +196,41 @@ class Root(object):
                      'proc',
                      'sys',
                     ]:
-            mock.util.mkdirIfAbsent(os.path.join(self.rootdir, item))
+            mock.util.mkdirIfAbsent(self.makeChrootPath(item))
 
         # touch files
         self.root_log.debug('touch required files')
-        for item in [os.path.join(self.rootdir, 'etc', 'mtab'),
-                     os.path.join(self.rootdir, 'etc', 'fstab'),
-                     os.path.join(self.rootdir, 'var', 'log', 'yum.log')]:
+        for item in [self.makeChrootPath('etc', 'mtab'),
+                     self.makeChrootPath('etc', 'fstab'),
+                     self.makeChrootPath('var', 'log', 'yum.log')]:
             mock.util.touch(item)
 
         # write in yum.conf into chroot
         # always truncate and overwrite (w+)
         self.root_log.debug('configure yum')
-        yumconf = os.path.join(self.rootdir, 'etc', 'yum', 'yum.conf')
+        yumconf = self.makeChrootPath('etc', 'yum', 'yum.conf')
         yumconf_fo = open(yumconf, 'w+')
         yumconf_fo.write(self.yum_conf_content)
         yumconf_fo.close()
 
         # symlink /etc/yum.conf to /etc/yum/yum.conf (FC6 requires)
         try:
-            os.unlink(os.path.join(self.rootdir, "etc", "yum.conf"))
+            os.unlink(self.makeChrootPath("etc", "yum.conf"))
         except OSError:
             pass
-        os.symlink('yum/yum.conf', os.path.join(self.rootdir, "etc", 
"yum.conf"))
+        os.symlink('yum/yum.conf', self.makeChrootPath("etc", "yum.conf"))
 
         # set up resolv.conf
         if self.use_host_resolv:
-            resolvdir = os.path.join(self.rootdir, 'etc')
-            resolvpath = os.path.join(self.rootdir, 'etc', 'resolv.conf')
+            resolvdir = self.makeChrootPath('etc')
+            resolvpath = self.makeChrootPath('etc', 'resolv.conf')
             if os.path.exists(resolvpath):
                 os.remove(resolvpath)
             shutil.copy2('/etc/resolv.conf', resolvdir)
 
         # files in /etc that need doing
         for key in self.chroot_file_contents:
-            p = os.path.join(self.rootdir, *key.split('/'))
+            p = self.makeChrootPath(key)
             if not os.path.exists(p):
                 # write file
                 fo = open(p, 'w+')
@@ -254,8 +262,8 @@ class Root(object):
     decorate(traceLog())
     def _setupDev(self):
         # files in /dev
-        mock.util.rmtree(os.path.join(self.rootdir, "dev"))
-        mock.util.mkdirIfAbsent(os.path.join(self.rootdir, "dev", "pts"))
+        mock.util.rmtree(self.makeChrootPath("dev"))
+        mock.util.mkdirIfAbsent(self.makeChrootPath("dev", "pts"))
         prevMask = os.umask(0000)
         devFiles = (
             (stat.S_IFCHR | 0666, os.makedev(1, 3), "dev/null"),
@@ -268,23 +276,23 @@ class Root(object):
         )
         for i in devFiles:
             # create node
-            os.mknod( os.path.join(self.rootdir, i[2]), i[0], i[1] )
+            os.mknod( self.makeChrootPath(i[2]), i[0], i[1])
             # set context. (only necessary if host running selinux enabled.)
             # fails gracefully if chcon not installed.
             mock.util.do("chcon --reference=/%s %s" %
-                (i[2], os.path.join(self.rootdir, i[2])), raiseExc=0)
+                (i[2], self.makeChrootPath(i[2])), raiseExc=0)
 
-        os.symlink("/proc/self/fd/0", os.path.join(self.rootdir, "dev/stdin"))
-        os.symlink("/proc/self/fd/1", os.path.join(self.rootdir, "dev/stdout"))
-        os.symlink("/proc/self/fd/2", os.path.join(self.rootdir, "dev/stderr"))
+        os.symlink("/proc/self/fd/0", self.makeChrootPath("dev/stdin"))
+        os.symlink("/proc/self/fd/1", self.makeChrootPath("dev/stdout"))
+        os.symlink("/proc/self/fd/2", self.makeChrootPath("dev/stderr"))
         os.umask(prevMask)
 
         # mount/umount
-        umntCmd = 'umount -n %s/dev/pts' % self.rootdir
+        umntCmd = 'umount -n %s' % self.makeChrootPath('/dev/pts')
         if umntCmd not in self.umountCmds:
             self.umountCmds.append(umntCmd)
 
-        mntCmd = 'mount -n -t devpts mock_chroot_devpts %s/dev/pts' % 
self.rootdir
+        mntCmd = 'mount -n -t devpts mock_chroot_devpts %s' % 
self.makeChrootPath('/dev/pts')
         if mntCmd not in self.mountCmds:
             self.mountCmds.append(mntCmd)
 
@@ -405,7 +413,7 @@ class Root(object):
                 gid=self.chrootgid,
                 )
 
-            bd_out = self.rootdir + self.builddir
+            bd_out = self.makeChrootPath(self.builddir)
             rpms = glob.glob(bd_out + '/RPMS/*.rpm')
             srpms = glob.glob(bd_out + '/SRPMS/*.rpm')
             packages = rpms + srpms
@@ -482,11 +490,11 @@ class Root(object):
 
     decorate(traceLog())
     def _makeBuildUser(self):
-        if not os.path.exists(os.path.join(self.rootdir, 'usr/sbin/useradd')):
+        if not os.path.exists(self.makeChrootPath('usr/sbin/useradd')):
             raise mock.exception.RootError, "Could not find useradd in chroot, 
maybe the install failed?"
 
         # safe and easy. blow away existing /builddir and completely re-create.
-        mock.util.rmtree(os.path.join(self.rootdir, self.homedir))
+        mock.util.rmtree(self.makeChrootPath(self.homedir))
         dets = { 'uid': self.chrootuid, 'gid': self.chrootgid, 'user': 
self.chrootuser, 'group': self.chrootgroup, 'home': self.homedir }
 
         self.doChroot('/usr/sbin/userdel -r %(user)s' % dets, raiseExc=False)
@@ -533,7 +541,7 @@ class Root(object):
         self.uidManager.becomeUser(self.chrootuid, self.chrootgid)
         try:
             # create dir structure
-            for subdir in ["%s/%s/%s" % (self.rootdir, self.builddir, s) for s 
in ('RPMS', 'SRPMS', 'SOURCES', 'SPECS', 'BUILD', 'originals')]:
+            for subdir in [self.makeChrootPath(self.builddir, s) for s in 
('RPMS', 'SRPMS', 'SOURCES', 'SPECS', 'BUILD', 'originals')]:
                 mock.util.mkdirIfAbsent(subdir)
 
             # change ownership so we can write to build home dir
@@ -543,7 +551,7 @@ class Root(object):
                     os.chmod(os.path.join(dirpath, path), 0755)
 
             # rpmmacros default
-            macrofile_out = '%s%s/.rpmmacros' % (self.rootdir, self.homedir)
+            macrofile_out = self.makeChrootPath(self.homedir, ".rpmmacros")
             rpmmacros = open(macrofile_out, 'w+')
             for key, value in self.macros.items():
                 rpmmacros.write( "%s %s\n" % (key, value) )
@@ -559,7 +567,7 @@ class Root(object):
     decorate(traceLog())
     def _copySrpmIntoChroot(self, srpm):
         srpmFilename = os.path.basename(srpm)
-        dest = self.rootdir + '/' + self.builddir + '/' + 'originals'
+        dest = self.makeChrootPath(self.builddir, 'originals')
         shutil.copy2(srpm, dest)
         return os.path.join(self.builddir, 'originals', srpmFilename)
 
diff --git a/py/mock/plugins/bind_mount.py b/py/mock/plugins/bind_mount.py
index 60f0f8b..df5e215 100644
--- a/py/mock/plugins/bind_mount.py
+++ b/py/mock/plugins/bind_mount.py
@@ -29,10 +29,10 @@ class BindMount(object):
         rootObj.bindMountObj = self
         rootObj.addHook("preinit",  self._bindMountPreInitHook)
         for srcdir, destdir in self.bind_opts['dirs']:
-            rootObj.umountCmds.append('umount -n %s/%s' % (rootObj.rootdir, 
destdir))
-            rootObj.mountCmds.append('mount -n --bind %s  %s/%s' % (srcdir, 
rootObj.rootdir, destdir))
+            rootObj.umountCmds.append('umount -n %s' % 
rootObj.makeChrootPath(destdir))
+            rootObj.mountCmds.append('mount -n --bind %s  %s' % (srcdir, 
rootObj.makeChrootPath(destdir)))
 
     decorate(traceLog())
     def _bindMountPreInitHook(self):
         for srcdir, destdir in self.bind_opts['dirs']:
-            mock.util.mkdirIfAbsent("%s/%s" % (self.rootObj.rootdir, destdir))
+            mock.util.mkdirIfAbsent(self.rootObj.makeChrootPath(destdir))
diff --git a/py/mock/plugins/ccache.py b/py/mock/plugins/ccache.py
index 7974b1f..77a9130 100644
--- a/py/mock/plugins/ccache.py
+++ b/py/mock/plugins/ccache.py
@@ -25,13 +25,12 @@ class CCache(object):
         self.rootObj = rootObj
         self.ccache_opts = conf
         self.ccachePath = self.ccache_opts['dir'] % self.ccache_opts
-        self.rootdir = rootObj.rootdir
         rootObj.ccacheObj = self
         rootObj.preExistingDeps = rootObj.preExistingDeps + " ccache "
         rootObj.addHook("prebuild", self._ccacheBuildHook)
         rootObj.addHook("preinit",  self._ccachePreInitHook)
-        rootObj.umountCmds.append('umount -n %s/tmp/ccache' % rootObj.rootdir)
-        rootObj.mountCmds.append('mount -n --bind %s  %s/tmp/ccache' % 
(self.ccachePath, rootObj.rootdir))
+        rootObj.umountCmds.append('umount -n %s' % 
rootObj.makeChrootPath("/tmp/ccache"))
+        rootObj.mountCmds.append('mount -n --bind %s  %s' % (self.ccachePath, 
rootObj.makeChrootPath("/tmp/ccache")))
 
     # =============
     # 'Private' API
@@ -49,7 +48,7 @@ class CCache(object):
     # cache.
     decorate(traceLog())
     def _ccachePreInitHook(self):
-        mock.util.mkdirIfAbsent(os.path.join(self.rootdir, 'tmp/ccache'))
+        mock.util.mkdirIfAbsent(self.rootObj.makeChrootPath('/tmp/ccache'))
         mock.util.mkdirIfAbsent(self.ccachePath)
         os.environ['PATH'] = "/tmp/ccache:%s" % (os.environ['PATH'])
         os.environ['CCACHE_DIR'] = "/tmp/ccache"
diff --git a/py/mock/plugins/yum_cache.py b/py/mock/plugins/yum_cache.py
index 5b371bb..bcdf465 100644
--- a/py/mock/plugins/yum_cache.py
+++ b/py/mock/plugins/yum_cache.py
@@ -30,14 +30,13 @@ class YumCache(object):
         self.yum_cache_opts = conf
         self.yumSharedCachePath = self.yum_cache_opts['dir'] % 
self.yum_cache_opts
         self.state = rootObj.state
-        self.rootdir = rootObj.rootdir
         self.online = rootObj.online
         rootObj.yum_cacheObj = self
         rootObj.addHook("preyum", self._yumCachePreYumHook)
         rootObj.addHook("postyum", self._yumCachePostYumHook)
         rootObj.addHook("preinit", self._yumCachePreInitHook)
-        rootObj.umountCmds.append('umount -n %s/var/cache/yum' % 
rootObj.rootdir)
-        rootObj.mountCmds.append('mount -n --bind %s  %s/var/cache/yum' % 
(self.yumSharedCachePath, rootObj.rootdir))
+        rootObj.umountCmds.append('umount -n %s' % 
rootObj.makeChrootPath('/var/cache/yum'))
+        rootObj.mountCmds.append('mount -n --bind %s  %s' % 
(self.yumSharedCachePath, rootObj.makeChrootPath('/var/cache/yum')))
         mock.util.mkdirIfAbsent(self.yumSharedCachePath)
         self.yumCacheLock = open(os.path.join(self.yumSharedCachePath, 
"yumcache.lock"), "a+")
 
@@ -65,7 +64,7 @@ class YumCache(object):
     decorate(traceLog())
     def _yumCachePreInitHook(self):
         getLog().info("enabled yum cache")
-        mock.util.mkdirIfAbsent(os.path.join(self.rootdir, 'var/cache/yum'))
+        mock.util.mkdirIfAbsent(self.rootObj.makeChrootPath('/var/cache/yum'))
 
         # lock so others dont accidentally use yum cache while we operate on 
it.
         self._yumCachePreYumHook()
--
Fedora-buildsys-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/fedora-buildsys-list

Reply via email to