diff --git a/bin/is b/bin/is index 8be4e7526d075dd3fe1865dcdb8a037a4ac8f653..dd8f95c544fafe643d991fadc1bb0ed37e51101a 100755 --- a/bin/is +++ b/bin/is @@ -154,9 +154,12 @@ def c_extract(parser, args): def c_get(parser, args): ''' - Get a remove image in current directory + Download a remote image in current directory ''' - raise NotImplementedError("Not yet implemented") + repoman = load_repositories(args) + for image in args.image: + img, repo = select_image(image, repoman) + img.download(".", payload=args.payload, force=args.force) def c_help(parser, args): ''' @@ -345,6 +348,11 @@ p_extract.set_defaults(func=c_extract) # get command parser p_get = subparsers.add_parser("get", help=c_get.__doc__.lower()) +p_get.add_argument("-p", action="store_true", dest="payload", default=False, + help="extract payload") +p_get.add_argument("-f", "--force", action="store_true", default=False, + help="overwrite existing image") +p_get.add_argument("image", nargs="+", help="image to extract") p_get.set_defaults(func=c_get) # help command parser diff --git a/installsystems/image.py b/installsystems/image.py index 9fae13be0d8d4c8d08fe0bbb8cfe6ef519e985a4..6cd5a4c64e8b1158124f7d710310d420009a0028 100644 --- a/installsystems/image.py +++ b/installsystems/image.py @@ -461,6 +461,30 @@ class PackageImage(Image): arrow(filename) out(self._tarball.get_str(filename)) + def download(self, directory, force=False, payload=False): + ''' + Download image in directory + ''' + # check if destination exists + directory = os.path.abspath(directory) + dest = os.path.join(directory, self.filename) + if not force and os.path.exists(dest): + raise Exception("Image destination already exists: %s" % dest) + # download + arrow("Downloading image in %s" % directory) + fs = istools.uopen(self.path) + fd = open(self.filename, "wb") + slen, smd5 = istools.copyfileobj(fs, fd) + fs.close() + fd.close() + if self.md5 != smd5: + raise Exception("Download image %s failed: Invalid MD5" % self.name) + if payload: + for payname in self.payload: + arrow("Downloading payload %s in %s" % (payname, directory)) + self.payload[payname].info + self.payload[payname].download(directory, force=force) + def extract(self, directory, force=False, payload=False): ''' Extract content of the image inside a repository @@ -620,6 +644,13 @@ class Payload(object): os.umask(umask) return 0666 & ~umask + @property + def filename(self): + ''' + Return the filename of the original payload + ''' + return "%s%s" % (self.name, self.extension) + @property def mtime(self): ''' @@ -632,7 +663,9 @@ class Payload(object): ''' Return a dict of info about current payload ''' - return {"md5": self.md5, + return {"name": self.name, + "filename": self.filename, + "md5": self.md5, "size": self.size, "isdir": self.isdir, "uid": self.uid, @@ -654,6 +687,31 @@ class Payload(object): if self._md5 != md5: raise Exception("Invalid MD5 of payload %s" % self._md5) + def download(self, dest, force=False): + ''' + Download payload in directory + ''' + # if dest is a directory try to create file inside + if os.path.isdir(dest): + dest = os.path.join(dest, self.filename) + # try to create leading directories + elif not os.path.exists(os.path.dirname(dest)): + istools.mkdir(os.path.dirname(dest)) + # check validity of dest + if os.path.exists(dest): + if os.path.isdir(dest): + raise Exception("Destination %s is a directory" % dest) + if not force: + raise Exception("File %s already exists" % dest) + # download + fs = istools.uopen(self.path) + fd = open(dest, "wb") + slen, smd5 = istools.copyfileobj(fs, fd) + fs.close() + fd.close() + if self.md5 != smd5: + raise Exception("Downloading payload %s failed: Invalid MD5" % self.name) + def extract(self, dest, force=False, filelist=None): ''' Extract payload into dest