--- a/.hgignore Mon May 12 13:34:49 2008 -0700
+++ b/.hgignore Mon May 12 14:47:31 2008 -0700
@@ -13,8 +13,10 @@
^src/man/pkg.1$
^src/man/pkg.5$
^src/man/pkg.depotd.1m$
+^src/man/pkgrecv.1$
^src/man/pkgsend.1$
^src/pkg$
+^src/pkgrecv$
^src/pkg.depotd$
^src/pkgdefs/SUNWipkg/prototype$
^src/pkgsend$
--- a/src/Makefile Mon May 12 13:34:49 2008 -0700
+++ b/src/Makefile Mon May 12 14:47:31 2008 -0700
@@ -23,6 +23,7 @@
#
# client.py -> /usr/bin/pkg
+# pull.py -> /usr/bin/pkgrecv
# publish.py -> /usr/bin/pkgsend
# depot.py -> /usr/lib/pkg.depotd
#
@@ -67,10 +68,11 @@
$(ROOTMAN1M) \
$(ROOTMAN5)
-PROGS = pkg pkgsend pkg.depotd
+PROGS = pkg pkgrecv pkgsend pkg.depotd
ROOTPROGS = \
$(ROOT)/usr/bin/pkg \
+ $(ROOT)/usr/bin/pkgrecv \
$(ROOT)/usr/bin/pkgsend \
$(ROOT)/usr/lib/pkg.depotd
@@ -241,6 +243,7 @@
PWD:sh = pwd
link:
ln -sf $(PWD)/client.py /usr/bin/pkg
+ ln -sf $(PWD)/pull.py /usr/bin/pkgrecv
ln -sf $(PWD)/publish.py /usr/bin/pkgsend
ln -sf $(PWD)/depot.py /usr/lib/pkg.depotd
ln -sf $(PWD)/modules /usr/lib/python2.4/vendor-packages/pkg
@@ -251,6 +254,7 @@
link-clean:
rm -f /usr/bin/pkg
+ rm -f /usr/bin/pkgrecv
rm -f /usr/bin/pkgsend
rm -f /usr/lib/pkg.depotd
rm -f /usr/lib/python2.4/vendor-packages/pkg
@@ -316,6 +320,9 @@
pkg: client.py
cp client.py pkg
+pkgrecv: pull.py
+ cp pull.py pkgrecv
+
pkgsend: publish.py
cp publish.py pkgsend
--- a/src/man/Makefile Mon May 12 13:34:49 2008 -0700
+++ b/src/man/Makefile Mon May 12 14:47:31 2008 -0700
@@ -30,7 +30,7 @@
ROOTMAN1M = $(ROOTMAN)/cat1m
ROOTMAN5 = $(ROOTMAN)/cat5
-MANPAGES = $(ROOTMAN1)/pkg.1 $(ROOTMAN1)/pkgsend.1 $(ROOTMAN1M)/pkg.depotd.1m $(ROOTMAN5)/pkg.5
+MANPAGES = $(ROOTMAN1)/pkg.1 $(ROOTMAN1)/pkgrecv.1 $(ROOTMAN1)/pkgsend.1 $(ROOTMAN1M)/pkg.depotd.1m $(ROOTMAN5)/pkg.5
all := TARGET = all
link := TARGET = link
@@ -45,12 +45,14 @@
link:
-mkdir -p /usr/share/man/cat1 /usr/share/man/cat1m /usr/share/man/cat5
ln -sf $(PWD)/pkg.1.txt /usr/share/man/cat1/pkg.1
+ ln -sf $(PWD)/pkgrecv.1.txt /usr/share/man/cat1/pkgrecv.1
ln -sf $(PWD)/pkgsend.1.txt /usr/share/man/cat1/pkgsend.1
ln -sf $(PWD)/pkg.depotd.1m.txt /usr/share/man/cat1m/pkg.depotd.1m
ln -sf $(PWD)/pkg.5.txt /usr/share/man/man5/pkg.5
link-clean:
rm -f /usr/share/man/cat1/pkg.1
+ rm -f /usr/share/man/cat1/pkgrecv.1
rm -f /usr/share/man/cat1/pkgsend.1
rm -f /usr/share/man/cat1m/pkg.depotd.1m
rm -f /usr/share/man/cat5/pkg.5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/man/pkgrecv.1.txt Mon May 12 14:47:31 2008 -0700
@@ -0,0 +1,81 @@
+User Commands pkgrecv(1)
+
+
+NAME
+ pkgrecv - image packaging system content retrieval utility
+
+SYNOPSIS
+ /usr/bin/pkgrecv [-d directory] -s server pkg...
+
+ /usr/bin/pkgrecv -s server -n
+
+DESCRIPTION
+ pkgrecv allows the user to download the contents of a package
+ from a server. The contents are retrieved in a format that can
+ easily be input to pkgsend(1) when used with the 'include'
+ subcommand.
+
+OPTIONS
+ The following options are supported:
+
+ -s repo_url The URL prefix of the server.
+
+ -d directory The directory where pkg content should be placed.
+ The default location is the current working
+ directory.
+
+ -n Instead of downloading packages, list the most recent
+ versions of the packages available at the specified
+ server.
+
+EXAMPLES
+ Example 1: List newest packages available from server test
+
+ $ pkgrecv -s http://test -n
+ pkg:/[email protected],5.11-0.79:20080221T125720Z
+ pkg:/[email protected],5.11-0.79:20080221T123955Z
+ pkg:/[email protected],5.11-0.79:20080221T125728Z
+ pkg:/[email protected],5.11-0.79:20080221T125730Z
+
+ Example 2: Receive the SUNWlibC, SUNWfreetype, and SUNWlibm
+ packages from example 1
+
+ $ pkgrecv -s http://test [email protected],5.11-0.79:20080221T125720Z
+ [email protected],5.11-0.79:20080221T123955Z
+ [email protected],5.11-0.79:20080221T125728Z
+
+
+EXIT STATUS
+ The following exit values are returned:
+
+ 0 Everything worked.
+
+ 1 Something bad happened.
+
+ 2 Invalid command line options were specified.
+
+FILES
+
+ATTRIBUTES
+ See attributes(5) for descriptions of the following attri-
+ butes:
+ ____________________________________________________________
+ | ATTRIBUTE TYPE | ATTRIBUTE VALUE |
+ |_____________________________|_____________________________|
+ | Availability | |
+ |_____________________________|_____________________________|
+
+SEE ALSO
+ pkgsend(1), attributes(5), pkg(5)
+
+NOTES
+ The image packaging system is an under-development feature.
+ Command names, invocation, formats, and operations are all subject
+ to change. Development is hosted in the OpenSolaris community
+ at
+
+ http://opensolaris.org/os/project/pkg/
+
+ Other package bundle formats can be created. Other forms of
+ package publication, via the underlying Python API or via the web
+ API, are also possible.
--- a/src/man/pkgsend.1.txt Mon May 12 13:34:49 2008 -0700
+++ b/src/man/pkgsend.1.txt Mon May 12 14:47:31 2008 -0700
@@ -10,7 +10,7 @@
/usr/bin/pkgsend open [-en] pkg_fmri
/usr/bin/pkgsend add action arguments
/usr/bin/pkgsend import bundlefile ...
- /usr/bin/pkgsend include manifest ...
+ /usr/bin/pkgsend include [-d basedir] manifest ...
/usr/bin/pkgsend close [-A]
/usr/bin/pkgsend send bundlefile ...
@@ -48,7 +48,7 @@
Add each given bundlefile (such as a SVr4 package) into the
current transaction.
- include manifest ...
+ include [-d basedir] manifest ...
Add resources associated with the multiple actions present in
each manifest file to the current transaction. Each line in the
file should be the string representation of an action. In
@@ -58,6 +58,9 @@
path to the file containing the data should be the second word on
the line.
+ If the user specifies the -d option, basedir is prepended to
+ the search path when locating files in the manifest.
+
close [-A]
Close current transaction. With -A, abandon the current
transaction.
--- a/src/publish.py Mon May 12 13:34:49 2008 -0700
+++ b/src/publish.py Mon May 12 14:47:31 2008 -0700
@@ -62,7 +62,7 @@
pkgsend open [-en] pkg_fmri
pkgsend add action arguments
pkgsend import bundlefile ...
- pkgsend include manifest ...
+ pkgsend include [-d basedir] manifest ...
pkgsend close [-A]
pkgsend send bundlefile
@@ -184,6 +184,14 @@
def trans_include(config, fargs):
+ basedir = None
+
+ opts, pargs = getopt.getopt(fargs, "d:")
+
+ for opt, arg in opts:
+ if opt == "-d":
+ basedir = arg
+
try:
trans_id = os.environ["PKG_TRANS_ID"]
except KeyError:
@@ -192,7 +200,7 @@
sys.exit(1)
t = trans.Transaction()
- for filename in fargs:
+ for filename in pargs:
f = file(filename)
for line in f:
line = line.strip() #
@@ -208,8 +216,15 @@
print >> sys.stderr, e[0]
sys.exit(1)
+ if basedir:
+ fullpath = args[1].lstrip(os.path.sep)
+ fullpath = os.path.join(basedir,
+ fullpath)
+ else:
+ fullpath = args[1]
+
def opener():
- return open(args[1], "rb")
+ return open(fullpath, "rb")
action.data = opener
else:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pull.py Mon May 12 14:47:31 2008 -0700
@@ -0,0 +1,309 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+import sys
+import os
+import traceback
+import getopt
+import urllib
+import tempfile
+import gettext
+import shutil
+
+import pkg.fmri
+import pkg.pkgtarfile as ptf
+import pkg.catalog as catalog
+import pkg.actions as actions
+from pkg.misc import versioned_urlopen
+
+def usage(usage_error = None):
+ """ Emit a usage message and optionally prefix it with a more
+ specific error message. Causes program to exit. """
+
+ pname = os.path.basename(sys.argv[0])
+ if usage_error:
+ print >> sys.stderr, pname + ": " + usage_error
+
+ print >> sys.stderr, _("""\
+Usage:
+ pkgrecv -s server [-d dir] pkgfmri ...
+ pkgrecv -s server -n""")
+
+ sys.exit(2)
+
+
+def error(error):
+ """ Emit an error message prefixed by the command name """
+
+ pname = os.path.basename(sys.argv[0])
+ print >> sys.stderr, pname + ": " + error
+
+def hashes_from_mfst(manifest):
+ """Given a path to a manifest, open the file and read through the
+ actions. Return a set of all content hashes found in the manifest."""
+
+ hashes = set()
+
+ try:
+ f = file(manifest, "r")
+ except:
+ error(_("Unable to open manifest: %s") % manifest)
+ sys.exit(1)
+
+ for line in f:
+ line = line.lstrip()
+ if not line or line[0] == "#":
+ continue
+
+ try:
+ action = actions.fromstr(line)
+ except:
+ continue
+
+ if hasattr(action, "hash"):
+ hashes.add(action.hash)
+
+ f.close()
+
+ return hashes
+
+def fetch_files_byhash(server_url, hashes, pkgdir):
+ """Given a list of files named by content hash, download from
+ server_url into pkgdir."""
+
+ req_dict = { }
+
+ for i, k in enumerate(hashes):
+ str = "File-Name-%s" % i
+ req_dict[str] = k
+
+ req_str = urllib.urlencode(req_dict)
+
+ try:
+ f, v = versioned_urlopen(server_url, "filelist", [0],
+ data = req_str)
+ except:
+ error(_("Unable to download files from: %s") % server_url)
+ sys.exit(1)
+
+ tar_stream = ptf.PkgTarFile.open(mode = "r|", fileobj = f)
+
+ if not os.path.exists(pkgdir):
+ try:
+ os.makedirs(pkgdir)
+ except:
+ error(_("Unable to create directory: %s") % pkgdir)
+ sys.exit(1)
+
+ for info in tar_stream:
+ hashval = info.name
+ try:
+ tar_stream.extract_to(info, pkgdir, hashval)
+ except:
+ error(_("Unable to extract file: %s") % info.name)
+ sys.exit(1)
+
+ tar_stream.close()
+ f.close()
+
+def fetch_manifest(server_url, fmri, basedir):
+ """Fetch the manifest for package-fmri 'fmri' from the server
+ in 'server_url'. Put manifest in a directory named by package stem"""
+
+ # Request manifest from server
+ try:
+ m, v = versioned_urlopen(server_url, "manifest", [0],
+ fmri.get_url_path())
+ except:
+ error(_("Unable to download manifest %s from %s") %
+ (fmri.get_url_path(), server_url))
+ sys.exit(1)
+
+ # join pkgname onto basedir. Manifest goes here
+ opath = os.path.join(basedir, urllib.quote(fmri.pkg_name, ""))
+
+ # Create directories if they don't exist
+ if not os.path.exists(opath):
+ try:
+ os.makedirs(opath)
+ except:
+ error(_("Unable to create directory: %s") % opath)
+ sys.exit(1)
+
+ # Open manifest
+ opath = os.path.join(opath, "manifest")
+ try:
+ ofile = file(opath, "w")
+ except:
+ error(_("Unable to open file: %s") % opath)
+ sys.exit(1)
+
+ # Read from server, write to file
+ try:
+ mfst = m.read()
+ except:
+ error(_("Error occurred while reading from: %s") % server_url)
+ sys.exit(1)
+
+ try:
+ ofile.write(mfst)
+ except:
+ error(_("Error occurred while writing to: %s") % opath)
+ sys.exit(1)
+
+ # Close it up
+ ofile.close()
+ m.close()
+
+ return opath
+
+def list_newest_fmris(cat):
+ """Look through the catalog 'cat' and return the newest version
+ of a fmri found for a given package."""
+
+ fm_hash = { }
+ fm_list = [ ]
+
+ # Order all fmris by package name
+ for f in cat.fmris():
+ if f.pkg_name in fm_hash:
+ fm_hash[f.pkg_name].append(f)
+ else:
+ fm_hash[f.pkg_name] = [ f ]
+
+ # sort each fmri list
+ for k in fm_hash.keys():
+ fm_hash[k].sort(reverse = True)
+ l = fm_hash[k]
+ fm_list.append(l[0])
+
+ for e in fm_list:
+ print e
+
+def fetch_catalog(server_url):
+ """Fetch the catalog from the server_url."""
+
+ # open connection for catalog
+ try:
+ c, v = versioned_urlopen(server_url, "catalog", [0])
+ except:
+ error(_("Unable to download catalog from: %s") % server_url)
+ sys.exit(1)
+
+ # make a tempdir for catalog
+ dl_dir = tempfile.mkdtemp()
+
+ # call catalog.recv to pull down catalog
+ try:
+ catalog.recv(c, dl_dir)
+ except:
+ error(_("Error while reading from: %s") % server_url)
+ sys.exit(1)
+
+ # close connection to server
+ c.close()
+
+ # instantiate catalog object
+ cat = catalog.Catalog(dl_dir)
+
+ # return (catalog, tmpdir path)
+ return cat, dl_dir
+
+def main_func():
+
+ server = None
+ basedir = None
+ newfmri = False
+
+ # XXX /usr/lib/locale is OpenSolaris-specific.
+ gettext.install("pkgrecv", "/usr/lib/locale")
+
+ try:
+ opts, pargs = getopt.getopt(sys.argv[1:], "s:d:n")
+ except getopt.GetoptError, e:
+ usage(_("Illegal option -- %s") % e.opt)
+
+ for opt, arg in opts:
+ if opt == "-s":
+ server = arg
+ if opt == "-d":
+ basedir = arg
+ if opt == "-n":
+ newfmri = True
+
+ if not server:
+ usage(_("must specify a server"))
+
+ if not server.startswith("http://"):
+ server = "http://%s" % server
+
+ if newfmri:
+ if pargs or len(pargs) > 0:
+ usage(_("-n takes no options"))
+
+ cat, dir = fetch_catalog(server)
+ list_newest_fmris(cat)
+ shutil.rmtree(dir)
+
+ else:
+ if pargs == None or len(pargs) == 0:
+ usage(_("must specify at least one pkgfmri"))
+
+ if not basedir:
+ basedir = os.getcwd()
+
+ for pkgfmri in pargs:
+ if not pkgfmri.startswith("pkg:/"):
+ pkgfmri = "pkg:/%s" % pkgfmri
+
+ try:
+ fmri = pkg.fmri.PkgFmri(pkgfmri)
+ except AssertionError:
+ error(_("pkgfmri %s needs a version string") %
+ pkgfmri)
+ return 1
+
+ mfstpath = fetch_manifest(server, fmri, basedir)
+ content_hashes = hashes_from_mfst(mfstpath)
+
+ fetch_files_byhash(server, content_hashes,
+ os.path.dirname(mfstpath))
+
+ return 0
+
+if __name__ == "__main__":
+ try:
+ ret = main_func()
+ except SystemExit, e:
+ raise e
+ except KeyboardInterrupt:
+ print "Interrupted"
+ sys.exit(1)
+ except:
+ traceback.print_exc()
+ sys.exit(99)
+ sys.exit(ret)
--- a/src/tests/cli-complete.py Mon May 12 13:34:49 2008 -0700
+++ b/src/tests/cli-complete.py Mon May 12 14:47:31 2008 -0700
@@ -54,6 +54,7 @@
import cli.t_pkg_list
import cli.t_commandline
import cli.t_upgrade
+ import cli.t_recv
import cli.t_rename
import cli.t_twodepot
@@ -68,6 +69,7 @@
cli.t_commandline.TestCommandLine,
cli.t_upgrade.TestUpgrade,
cli.t_circular_dependencies.TestCircularDependencies,
+ cli.t_recv.TestPkgRecv,
cli.t_rename.TestRename,
cli.t_twodepot.TestTwoDepots ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_recv.py Mon May 12 14:47:31 2008 -0700
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+import sys
+import testutils
+if __name__ == "__main__":
+ testutils.setup_environment("../../../proto")
+
+import os
+import shutil
+import tempfile
+import unittest
+
+class TestPkgRecv(testutils.ManyDepotTestCase):
+
+ bronze10 = """
+ open [email protected],5.11-0
+ add dir mode=0755 owner=root group=bin path=/usr
+ add dir mode=0755 owner=root group=bin path=/usr/bin
+ add file /tmp/sh mode=0555 owner=root group=bin path=/usr/bin/sh
+ add link path=/usr/bin/jsh target=./sh
+ add hardlink path=/lib/libc.bronze target=/lib/libc.so.1
+ add file /tmp/bronze1 mode=0444 owner=root group=bin path=/etc/bronze1
+ add file /tmp/bronze2 mode=0444 owner=root group=bin path=/etc/bronze2
+ add file /tmp/bronzeA1 mode=0444 owner=root group=bin path=/A/B/C/D/E/F/bronzeA1
+ add depend fmri=pkg:/[email protected] type=require
+ add license /tmp/copyright2 license=copyright
+ close
+ """
+
+ bronze20 = """
+ open [email protected],5.11-0
+ add dir mode=0755 owner=root group=bin path=/etc
+ add dir mode=0755 owner=root group=bin path=/lib
+ add file /tmp/sh mode=0555 owner=root group=bin path=/usr/bin/sh
+ add file /tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.bronze
+ add link path=/usr/bin/jsh target=./sh
+ add hardlink path=/lib/libc.bronze2.0.hardlink target=/lib/libc.so.1
+ add file /tmp/bronze1 mode=0444 owner=root group=bin path=/etc/bronze1
+ add file /tmp/bronze2 mode=0444 owner=root group=bin path=/etc/amber2
+ add license /tmp/copyright3 license=copyright
+ add file /tmp/bronzeA2 mode=0444 owner=root group=bin path=/A1/B2/C3/D4/E5/F6/bronzeA2
+ add depend fmri=pkg:/[email protected] type=require
+ close
+ """
+
+ misc_files = [ "/tmp/bronzeA1", "/tmp/bronzeA2",
+ "/tmp/bronze1", "/tmp/bronze2",
+ "/tmp/copyright2", "/tmp/copyright3",
+ "/tmp/libc.so.1", "/tmp/sh"]
+
+ def setUp(self):
+ """ Start two depots.
+ depot 1 gets foo and moo, depot 2 gets foo and bar
+ depot1 is mapped to authority test1 (preferred)
+ depot2 is mapped to authority test2 """
+
+ testutils.ManyDepotTestCase.setUp(self, 2)
+
+ for p in self.misc_files:
+ f = open(p, "w")
+ # write the name of the file into the file, so that
+ # all files have differing contents
+ f.write(p)
+ f.close()
+ self.debug("wrote %s" % p)
+
+ self.durl1 = self.dcs[1].get_depot_url()
+ self.pkgsend_bulk(self.durl1, self.bronze10)
+ self.pkgsend_bulk(self.durl1, self.bronze20)
+
+ self.durl2 = self.dcs[2].get_depot_url()
+ self.tempdir = tempfile.mkdtemp()
+
+
+ def tearDown(self):
+ testutils.ManyDepotTestCase.tearDown(self)
+ for p in self.misc_files:
+ os.remove(p)
+ shutil.rmtree(self.tempdir)
+
+ def test_recv_send(self):
+ rc, output = self.pkgrecv(self.durl1,
+ "-n | grep [email protected]", out = True)
+
+ # Pull the pkg name out of the output from the last cmd
+ outwords = output.split()
+
+ # recv the pkg
+ recvcmd = "-d %s %s" % (self.tempdir, outwords[0])
+ self.pkgrecv(self.durl1, recvcmd)
+
+ # now send it to another depot
+ self.pkgsend(self.durl2, "open [email protected]")
+
+ basedir = os.path.join(self.tempdir, "bronze")
+ manifest = os.path.join(basedir, "manifest")
+
+ cmd = "include -d %s %s" % (basedir, manifest)
+
+ self.pkgsend(self.durl2, cmd)
+ self.pkgsend(self.durl2, "close")
+
+ def test_bad_opts(self):
+ self.pkgrecv("", "-n", exit = 2)
+ self.pkgrecv(self.durl1, "-!", exit = 2)
+ self.pkgrecv(self.durl1, "-p foo", exit = 2)
+ self.pkgrecv(self.durl1, "-d %s [email protected]" % self.tempdir,
+ exit = 1)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
--- a/src/tests/cli/t_upgrade.py Mon May 12 13:34:49 2008 -0700
+++ b/src/tests/cli/t_upgrade.py Mon May 12 14:47:31 2008 -0700
@@ -133,7 +133,7 @@
# write the name of the file into the file, so that
# all files have differing contents
f.write(p)
- f.close
+ f.close()
self.debug("wrote %s" % p)
def tearDown(self):
--- a/src/tests/cli/testutils.py Mon May 12 13:34:49 2008 -0700
+++ b/src/tests/cli/testutils.py Mon May 12 14:47:31 2008 -0700
@@ -323,6 +323,33 @@
return retcode
+ def pkgrecv(self, server_url, command, exit = 0, out = False,
+ comment = ""):
+
+ cmdline = "pkgrecv -s %s %s" % (server_url, command)
+ self.debugcmd(cmdline)
+
+ p = subprocess.Popen(cmdline, shell = True,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.STDOUT)
+
+ output = p.stdout.read()
+ retcode = p.wait()
+ self.debugresult(retcode, output)
+
+ if retcode == 99:
+ raise TracebackException(cmdline, output, comment,
+ debug = self.get_debugbuf())
+ elif retcode != exit:
+ raise UnexpectedExitCodeException(cmdline,
+ exit, retcode, output, comment,
+ debug = self.get_debugbuf())
+
+ if out:
+ return retcode, output
+
+ return retcode
+
def pkgsend(self, depot_url, command, exit = 0, comment = ""):
cmdline = "pkgsend -s %s %s" % (depot_url, command)