Revision ae99b37d

b/kamaki/cli/commands/pithos_cli.py
987 987

  
988 988
@command(pithos_cmds)
989 989
class store_download(_store_container_command):
990
    """Download remote object as local file"""
990
    """Download remote object as local file
991
    If local destination is a directory:
992
    *   download <container>:<path> <local dir>
993
    will download all files on <container> prefixed as <path>,
994
    to <local dir>/<full path>
995
    *   download <container>:<path> <local dir> --exact-match
996
    will download only one file, exactly matching <path>
997
    """
991 998

  
992 999
    arguments = dict(
993 1000
        resume=FlagArgument('Resume instead of overwrite', '--resume'),
......
1009 1016
        progress_bar=ProgressBarArgument(
1010 1017
            'do not show progress bar',
1011 1018
            '--no-progress-bar',
1012
            default=False)
1019
            default=False),
1020
        exact_match=FlagArgument(
1021
            'Download only the object that matches path exactly',
1022
            '--exact-match')
1013 1023
    )
1014 1024

  
1015
    def _output_stream(self, local_path):
1025
    def _output_streams(self, local_path):
1016 1026
        if local_path is None:
1017
            return stdout
1018
        return open(
1019
            path.abspath(local_path), 'rwb+' if self['resume'] else 'wb+')
1027
            return [(stdout, self.path)]
1028
        outpath = path.abspath(local_path)
1029
        wmode = 'rwb+' if self['resume'] else 'wb+'
1030
        try:
1031
            return [(open(outpath, wmode), self.path)]
1032
        except IOError as ioe:
1033
            if 'is a directory' in ('%s' % ioe).lower():
1034
                if self['exact_match']:
1035
                    return [(
1036
                            open('%s/%s' % (outpath, self.path), wmode),
1037
                            self.path
1038
                        )]
1039
                remotes = self.client.container_get(
1040
                    prefix=self.path,
1041
                    if_modified_since=self['if_modified_since'],
1042
                    if_unmodified_since=self['if_unmodified_since'])
1043
                return [(
1044
                            open('%s/%s' % (outpath, remote['name']), wmode),
1045
                            remote['name']
1046
                        ) for remote in remotes.json]
1047
            raise
1020 1048

  
1021 1049
    @errors.generic.all
1022 1050
    @errors.pithos.connection
......
1024 1052
    @errors.pithos.object_path
1025 1053
    @errors.pithos.local_path
1026 1054
    def _run(self, local_path):
1027
        out = self._output_stream(local_path)
1055
        streams = self._output_streams(local_path)
1028 1056
        poolsize = self['poolsize']
1029 1057
        if poolsize:
1030 1058
            self.client.POOL_SIZE = int(poolsize)
1031
        try:
1032
            (progress_bar, download_cb) = self._safe_progress_bar(
1033
                'Downloading')
1034
            self.client.download_object(
1059
        if not streams:
1060
            raiseCLIError('No objects prefixed as %s on container %s' % (
1035 1061
                self.path,
1036
                out,
1037
                download_cb=download_cb,
1038
                range=self['range'],
1039
                version=self['object_version'],
1040
                if_match=self['if_match'],
1041
                resume=self['resume'],
1042
                if_none_match=self['if_none_match'],
1043
                if_modified_since=self['if_modified_since'],
1044
                if_unmodified_since=self['if_unmodified_since'])
1062
                self.container))
1063
        try:
1064
            for out, rpath in streams:
1065
                print('\nFrom %s:%s to %s/%s' % (
1066
                    self.container,
1067
                    rpath,
1068
                    local_path,
1069
                    rpath))
1070
                (progress_bar,
1071
                    download_cb) = self._safe_progress_bar('Downloading')
1072
                self.client.download_object(
1073
                    rpath,
1074
                    out,
1075
                    download_cb=download_cb,
1076
                    range=self['range'],
1077
                    version=self['object_version'],
1078
                    if_match=self['if_match'],
1079
                    resume=self['resume'],
1080
                    if_none_match=self['if_none_match'],
1081
                    if_modified_since=self['if_modified_since'],
1082
                    if_unmodified_since=self['if_unmodified_since'])
1045 1083
        except KeyboardInterrupt:
1046 1084
            from threading import enumerate as activethreads
1047 1085
            stdout.write('\nFinishing active threads ')

Also available in: Unified diff