add version support
[pithos] / tools / store
index 62d24dc..584273c 100755 (executable)
@@ -57,7 +57,7 @@ class Command(object):
         
         self.parser = parser
         self.args = args
-    
+
     def add_options(self, parser):
         pass
 
@@ -105,7 +105,7 @@ class List(Command):
             self.list_objects(container)
         else:
             self.list_containers()
-    
+
     def list_containers(self):
         params = {'limit':self.limit, 'marker':self.marker}
         headers = {'IF_MODIFIED_SINCE':self.if_modified_since,
@@ -148,6 +148,9 @@ class Meta(Command):
                           default=False, help='show metadata until that date')
         parser.add_option('--format', action='store', dest='format',
                           default='%d/%m/%Y', help='format to parse until date')
+        parser.add_option('--version', action='store', dest='version',
+                          default=None, help='show specific version \
+                                  (applies only for objects)')
 
     def execute(self, path=''):
         container, sep, object = path.partition('/')
@@ -156,7 +159,8 @@ class Meta(Command):
             self.until = int(_time.mktime(t))
         if object:
             meta = self.client.retrieve_object_metadata(container, object,
-                                                        self.restricted)
+                                                        self.restricted,
+                                                        self.version)
         elif container:
             meta = self.client.retrieve_container_metadata(container,
                                                            self.restricted,
@@ -218,6 +222,11 @@ class GetObject(Command):
         parser.add_option('-f', action='store', type='str',
                           dest='file', default=None,
                           help='save output in file')
+        parser.add_option('--version', action='store', type='str',
+                          dest='version', default='list',
+                          help='if \'list\' and in detailed mode get object\'s \
+                               full version list otherwise get the specific \
+                               version')
 
     def execute(self, path):
         headers = {}
@@ -230,18 +239,17 @@ class GetObject(Command):
             headers[a.replace('-', '_').upper()] = getattr(self, a)
         container, sep, object = path.partition('/')
         data = self.client.retrieve_object(container, object, self.detail,
-                                          headers)
-        if self.file:
-            if self.detail:
-                f = self.file and open(self.file, 'w') or stdout
-                data = json.loads(data)
-                print_dict(data, f=f)
+                                          headers, self.version)
+        f = self.file and open(self.file, 'w') or stdout
+        if self.detail:
+            data = json.loads(data)
+            if self.version == 'list':
+                print_versions(data, f=f)
             else:
-                fw = open(self.file, 'w')
-                fw.write(data)
-                fw.close()
+                print_dict(data, f=f)
         else:
-            print data
+            f.write(data)
+        f.close()
 
 @cli_command('put')
 class PutObject(Command):
@@ -263,7 +271,7 @@ class PutObject(Command):
                           dest='manifest', default=None,
                           help='use for large file support')
         parser.add_option('--touch', action='store_true',
-                          dest='touch', default=True,
+                          dest='touch', default=False,
                           help='create object with zero data')
 
     def execute(self, path, srcpath='-', *args):
@@ -334,11 +342,11 @@ class SetMeta(Command):
 @cli_command('update')
 class UpdateObject(Command):
     syntax = '<container>/<object> path [key=val] [...]'
-    description = 'update object metadata/data'
+    description = 'update object metadata/data (default mode: append)'
     
     def add_options(self, parser):
         parser.add_option('-a', action='store_true', dest='append',
-                          default=None, help='append data')
+                          default=True, help='append data')
         parser.add_option('--start', action='store',
                           dest='start',
                           default=None, help='range of data to be updated')
@@ -356,7 +364,7 @@ class UpdateObject(Command):
                           dest='manifest', default=None,
                           help='use for large file support')
 
-    def execute(self, path, srcpath, *args):
+    def execute(self, path, srcpath='-', *args):
         headers = {}
         if self.manifest:
             headers['X_OBJECT_MANIFEST'] = self.manifest
@@ -439,6 +447,14 @@ def print_list(l, verbose=False, f=stdout):
         else:
             f.write('%s\n' % elem)
 
+def print_versions(data, f=stdout):
+    if 'versions' not in data:
+        f.write('%s\n' %data)
+        return
+    f.write('versions:\n')
+    for id, t in data['versions']:
+        f.write('%s @ %s\n' % (str(id).rjust(30), datetime.fromtimestamp(t)))
+
 def main():
     try:
         name = argv[1]
@@ -451,12 +467,13 @@ def main():
     
     try:
         cmd.execute(*cmd.args)
-    except TypeError:
+    except TypeError, e:
+        print e
         cmd.parser.usage = '%%prog %s [options] %s' % (name, cmd.syntax)
         cmd.parser.print_help()
         exit(1)
     except Fault, f:
-        print f.data
+        print f.status, f.data
 
 if __name__ == '__main__':
     main()