Revision 761e0cbf kamaki/cli/commands/pithos_cli.py

b/kamaki/cli/commands/pithos_cli.py
526 526
        self._run()
527 527

  
528 528

  
529
@command(pithos_cmds)
530
class store_copy(_store_container_command):
531
    """Copy objects from container to (another) container
532
    Semantics:
533
    copy cont:path dir
534
    .   transfer path as dir/path
535
    copy cont:path cont2:
536
    .   trasnfer all <obj> prefixed with path to container cont2
537
    copy cont:path [cont2:]path2
538
    .   transfer path to path2
539
    Use options:
540
    1. <container1>:<path1> [container2:]<path2> : if container2 is not given,
541
    destination is container1:path2
542
    2. <container>:<path1> <path2> : make a copy in the same container
543
    3. Can use --container= instead of <container1>
544
    """
529
class _source_destination_command(_store_container_command):
545 530

  
546 531
    arguments = dict(
547
        destination_container=ValueArgument(
548
            'use it if destination container name contains a : character',
549
            '--dst-container'),
550
        source_version=ValueArgument(
551
            'copy specific version',
552
            '--source-version'),
553
        public=ValueArgument('make object publicly accessible', '--public'),
554
        content_type=ValueArgument(
555
            'change object\'s content type',
556
            '--content-type'),
557
        recursive=FlagArgument(
558
            'copy directory and contents',
559
            ('-r', '--recursive')),
560
        prefix=FlagArgument(
561
            'Match objects prefixed with src path (feels like src_path*)',
562
            '--with-prefix',
563
            default=''),
564
        suffix=ValueArgument(
565
            'Suffix of source objects (feels like *suffix)',
566
            '--with-suffix',
567
            default=''),
568
        add_prefix=ValueArgument('Prefix targets', '--add-prefix', default=''),
569
        add_suffix=ValueArgument('Suffix targets', '--add-suffix', default=''),
570
        prefix_replace=ValueArgument(
571
            'Prefix of src to replace with dst path + add_prefix, if matched',
572
            '--prefix-to-replace',
573
            default=''),
574
        suffix_replace=ValueArgument(
575
            'Suffix of src to replace with add_suffix, if matched',
576
            '--suffix-to-replace',
577
            default='')
532
        recursive=FlagArgument('', ('-r', '--recursive')),
533
        prefix=FlagArgument('', '--with-prefix', default=''),
534
        suffix=ValueArgument('', '--with-suffix', default=''),
535
        add_prefix=ValueArgument('', '--add-prefix', default=''),
536
        add_suffix=ValueArgument('', '--add-suffix', default=''),
537
        prefix_replace=ValueArgument('', '--prefix-to-replace', default=''),
538
        suffix_replace=ValueArgument('', '--suffix-to-replace', default='')
578 539
    )
579 540

  
541
    def __init__(self, arguments={}):
542
        self.arguments.update(arguments)
543
        super(_source_destination_command, self).__init__(self.arguments)
544

  
580 545
    def _get_all(self, prefix):
581 546
        return self.client.container_get(prefix=prefix).json
582 547

  
......
615 580
        srcobj['name'] = src_path
616 581
        return srcobj
617 582

  
618
    def _objlist(self, dst_cont, dst_path):
583
    def src_dst_pairs(self, dst_cont, dst_path):
619 584
        src_iter = self._get_src_objects(self.container, self.path)
620 585
        src_N = isinstance(src_iter, tuple)
621 586
        add_prefix = self['add_prefix'].strip('/')
......
670 635
            obj = obj[:-len(self['suffix_replace'])]
671 636
        return add_prefix + obj + self['add_suffix']
672 637

  
638

  
639
@command(pithos_cmds)
640
class store_copy(_source_destination_command):
641
    """Copy objects from container to (another) container
642
    Semantics:
643
    copy cont:path dir
644
    .   transfer path as dir/path
645
    copy cont:path cont2:
646
    .   trasnfer all <obj> prefixed with path to container cont2
647
    copy cont:path [cont2:]path2
648
    .   transfer path to path2
649
    Use options:
650
    1. <container1>:<path1> [container2:]<path2> : if container2 is not given,
651
    destination is container1:path2
652
    2. <container>:<path1> <path2> : make a copy in the same container
653
    3. Can use --container= instead of <container1>
654
    """
655

  
656
    arguments = dict(
657
        destination_container=ValueArgument(
658
            'use it if destination container name contains a : character',
659
            '--dst-container'),
660
        source_version=ValueArgument(
661
            'copy specific version',
662
            '--source-version'),
663
        public=ValueArgument('make object publicly accessible', '--public'),
664
        content_type=ValueArgument(
665
            'change object\'s content type',
666
            '--content-type'),
667
        recursive=FlagArgument(
668
            'copy directory and contents',
669
            ('-r', '--recursive')),
670
        prefix=FlagArgument(
671
            'Match objects prefixed with src path (feels like src_path*)',
672
            '--with-prefix',
673
            default=''),
674
        suffix=ValueArgument(
675
            'Suffix of source objects (feels like *suffix)',
676
            '--with-suffix',
677
            default=''),
678
        add_prefix=ValueArgument('Prefix targets', '--add-prefix', default=''),
679
        add_suffix=ValueArgument('Suffix targets', '--add-suffix', default=''),
680
        prefix_replace=ValueArgument(
681
            'Prefix of src to replace with dst path + add_prefix, if matched',
682
            '--prefix-to-replace',
683
            default=''),
684
        suffix_replace=ValueArgument(
685
            'Suffix of src to replace with add_suffix, if matched',
686
            '--suffix-to-replace',
687
            default='')
688
    )
689

  
673 690
    @errors.generic.all
674 691
    @errors.pithos.connection
675 692
    @errors.pithos.container
676 693
    def _run(self, dst_cont, dst_path):
677 694
        no_source_object = True
678
        for src_object, dst_object in self._objlist(dst_cont, dst_path):
695
        for src_object, dst_object in self.src_dst_pairs(dst_cont, dst_path):
679 696
            no_source_object = False
680 697
            self.client.copy_object(
681 698
                src_container=self.container,
......
703 720

  
704 721

  
705 722
@command(pithos_cmds)
706
class store_move(_store_container_command):
707
    """Move/rename objects
723
class store_move(_source_destination_command):
724
    """Move/rename objects from container to (another) container
708 725
    Semantics:
709
    move cont:path path2
710
    .   will move all <obj> prefixed with path, as path2<obj>
711
    .   or as path2 if path corresponds to just one whole object
726
    move cont:path dir
727
    .   rename path as dir/path
712 728
    move cont:path cont2:
713
    .   will move all <obj> prefixed with path to container cont2
714
    move cont:path [cont2:]path2 --exact-match
715
    .   will move at most one <obj> as a new object named path2,
716
    .   provided path corresponds to a whole object path
717
    move cont:path [cont2:]path2 --replace
718
    .   will move all <obj> prefixed with path, replacing path with path2
719
    where <obj> is a full file or directory object path.
729
    .   trasnfer all <obj> prefixed with path to container cont2
730
    move cont:path [cont2:]path2
731
    .   transfer path to path2
720 732
    Use options:
721
    1. <container1>:<path1> [container2:]<path2> : if container2 not given,
733
    1. <container1>:<path1> [container2:]<path2> : if container2 is not given,
722 734
    destination is container1:path2
723
    2. <container>:<path1> path2 : rename
735
    2. <container>:<path1> <path2> : move in the same container
724 736
    3. Can use --container= instead of <container1>
725 737
    """
726 738

  
......
728 740
        destination_container=ValueArgument(
729 741
            'use it if destination container name contains a : character',
730 742
            '--dst-container'),
731
        source_version=ValueArgument('specify version', '--source-version'),
732
        public=FlagArgument('make object publicly accessible', '--public'),
733
        content_type=ValueArgument('modify content type', '--content-type'),
734
        recursive=FlagArgument('up to delimiter /', ('-r', '--recursive')),
735
        exact_match=FlagArgument(
736
            'Copy only the object that fully matches path',
737
            '--exact-match'),
738
        replace=FlagArgument('Replace src. path with dst. path', '--replace')
743
        source_version=ValueArgument(
744
            'copy specific version',
745
            '--source-version'),
746
        public=ValueArgument('make object publicly accessible', '--public'),
747
        content_type=ValueArgument(
748
            'change object\'s content type',
749
            '--content-type'),
750
        recursive=FlagArgument(
751
            'copy directory and contents',
752
            ('-r', '--recursive')),
753
        prefix=FlagArgument(
754
            'Match objects prefixed with src path (feels like src_path*)',
755
            '--with-prefix',
756
            default=''),
757
        suffix=ValueArgument(
758
            'Suffix of source objects (feels like *suffix)',
759
            '--with-suffix',
760
            default=''),
761
        add_prefix=ValueArgument('Prefix targets', '--add-prefix', default=''),
762
        add_suffix=ValueArgument('Suffix targets', '--add-suffix', default=''),
763
        prefix_replace=ValueArgument(
764
            'Prefix of src to replace with dst path + add_prefix, if matched',
765
            '--prefix-to-replace',
766
            default=''),
767
        suffix_replace=ValueArgument(
768
            'Suffix of src to replace with add_suffix, if matched',
769
            '--suffix-to-replace',
770
            default='')
739 771
    )
740 772

  
741
    def _objlist(self, dst_path):
742
        if self['exact_match']:
743
            return [(dst_path or self.path, self.path)]
744
        r = self.client.container_get(prefix=self.path)
745
        if len(r.json) == 1:
746
            obj = r.json[0]
747
            return [(obj['name'], dst_path or obj['name'])]
748
        return [(
749
            obj['name'],
750
            '%s%s' % (
751
                dst_path,
752
                obj['name'][len(self.path) if self['replace'] else 0:]
753
            )) for obj in r.json]
754

  
755 773
    @errors.generic.all
756 774
    @errors.pithos.connection
757 775
    @errors.pithos.container
758 776
    def _run(self, dst_cont, dst_path):
759 777
        no_source_object = True
760
        for src_object, dst_object in self._objlist(dst_path):
778
        for src_object, dst_object in self.src_dst_pairs(dst_cont, dst_path):
761 779
            no_source_object = False
762 780
            self.client.move_object(
763 781
                src_container=self.container,
764 782
                src_object=src_object,
765
                dst_container=dst_cont or self.container,
783
                dst_container=dst_cont,
766 784
                dst_object=dst_object,
767 785
                source_version=self['source_version'],
768 786
                public=self['public'],
......
779 797
        super(self.__class__, self)._run(
780 798
            source_container___path,
781 799
            path_is_optional=False)
782
        (dst_cont, dst_path) = self._dest_container_path(
800
        (dst_cnt, dst_path) = self._dest_container_path(
783 801
            destination_container___path)
784
        self._run(dst_cont=dst_cont, dst_path=dst_path or '')
802
        self._run(dst_cont=dst_cnt or self.container, dst_path=dst_path or '')
785 803

  
786 804

  
787 805
@command(pithos_cmds)

Also available in: Unified diff