@@ -589,6 +589,207 @@ def test_files(self):
589
589
590
590
self ._run_command (['delete_file_version' , '9999' ], expected_stdout , '' , 0 )
591
591
592
+ def test_copy_file (self ):
593
+ self ._authorize_account ()
594
+ self ._create_my_bucket ()
595
+
596
+ with TempDir () as temp_dir :
597
+ local_file1 = self ._make_local_file (temp_dir , 'file1.txt' )
598
+ # For this test, use a mod time without millis. My mac truncates
599
+ # millis and just leaves seconds.
600
+ mod_time = 1500111222
601
+ os .utime (local_file1 , (mod_time , mod_time ))
602
+ self .assertEqual (1500111222 , os .path .getmtime (local_file1 ))
603
+
604
+ # Upload a file
605
+ expected_stdout = '''
606
+ URL by file name: http://download.example.com/file/my-bucket/file1.txt
607
+ URL by fileId: http://download.example.com/b2api/{api_version}/b2_download_file_by_id?fileId=9999
608
+ {{
609
+ "action": "upload",
610
+ "fileId": "9999",
611
+ "fileName": "file1.txt",
612
+ "size": 11,
613
+ "uploadTimestamp": 5000
614
+ }}
615
+ '''
616
+
617
+ self ._run_command (
618
+ ['upload_file' , '--noProgress' , 'my-bucket' , local_file1 , 'file1.txt' ],
619
+ expected_stdout , '' , 0
620
+ )
621
+
622
+ # Copy File
623
+ expected_stdout = '''
624
+ {{
625
+ "accountId": "{account_id}",
626
+ "action": "copy",
627
+ "bucketId": "bucket_0",
628
+ "contentLength": 11,
629
+ "contentSha1": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
630
+ "contentType": "b2/x-auto",
631
+ "fileId": "9998",
632
+ "fileInfo": {{
633
+ "src_last_modified_millis": "1500111222000"
634
+ }},
635
+ "fileName": "file1_copy.txt",
636
+ "uploadTimestamp": 5001
637
+ }}
638
+ '''
639
+ self ._run_command (
640
+ ['copy_file' , '9999' , 'my-bucket' , 'file1_copy.txt' ], expected_stdout , '' , 0
641
+ )
642
+
643
+ # Copy File with range parameter
644
+ expected_stdout = '''
645
+ {{
646
+ "accountId": "{account_id}",
647
+ "action": "copy",
648
+ "bucketId": "bucket_0",
649
+ "contentLength": 6,
650
+ "contentSha1": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
651
+ "contentType": "b2/x-auto",
652
+ "fileId": "9997",
653
+ "fileInfo": {{
654
+ "src_last_modified_millis": "1500111222000"
655
+ }},
656
+ "fileName": "file1_copy.txt",
657
+ "uploadTimestamp": 5002
658
+ }}
659
+ '''
660
+ self ._run_command (
661
+ ['copy_file' , '--range' , '3,9' , '9999' , 'my-bucket' , 'file1_copy.txt' ],
662
+ expected_stdout ,
663
+ '' ,
664
+ 0 ,
665
+ )
666
+
667
+ # Invalid range size
668
+ expected_stderr = "ERROR: --range can must have exact 2 values, start and end\n "
669
+ self ._run_command (
670
+ ['copy_file' , '--range' , '3,9,11' , '9999' , 'my-bucket' , 'file1_copy.txt' ],
671
+ '' ,
672
+ expected_stderr ,
673
+ 1 ,
674
+ )
675
+
676
+ # Invalid range values
677
+ expected_stderr = "ERROR: --range start,end must be integers\n "
678
+ self ._run_command (
679
+ ['copy_file' , '--range' , '3,abc' , '9999' , 'my-bucket' , 'file1_copy.txt' ],
680
+ '' ,
681
+ expected_stderr ,
682
+ 1 ,
683
+ )
684
+
685
+ # Invalid metadata value
686
+ expected_stderr = "ERROR: --metadataDirective must be either 'copy' or 'replace'\n "
687
+ self ._run_command (
688
+ [
689
+ 'copy_file' , '--metadataDirective' , 'random' , '9999' , 'my-bucket' ,
690
+ 'file1_copy.txt'
691
+ ],
692
+ '' ,
693
+ expected_stderr ,
694
+ 1 ,
695
+ )
696
+
697
+ # Invalid metadata copy with file info
698
+ expected_stderr = "ERROR: content_type and file_info should be None when metadata_directive is COPY\n "
699
+ self ._run_command (
700
+ [
701
+ 'copy_file' ,
702
+ '--metadataDirective' ,
703
+ 'copy' ,
704
+ '--info' ,
705
+ 'a=b' ,
706
+ '9999' ,
707
+ 'my-bucket' ,
708
+ 'file1_copy.txt' ,
709
+ ],
710
+ '' ,
711
+ expected_stderr ,
712
+ 1 ,
713
+ )
714
+
715
+ # Invalid metadata replace without file info
716
+ expected_stderr = "ERROR: content_type cannot be None when metadata_directive is REPLACE\n "
717
+ self ._run_command (
718
+ [
719
+ 'copy_file' , '--metadataDirective' , 'replace' , '9999' , 'my-bucket' ,
720
+ 'file1_copy.txt'
721
+ ],
722
+ '' ,
723
+ expected_stderr ,
724
+ 1 ,
725
+ )
726
+
727
+ # replace with content type and file info
728
+ expected_stdout = '''
729
+ {{
730
+ "accountId": "{account_id}",
731
+ "action": "copy",
732
+ "bucketId": "bucket_0",
733
+ "contentLength": 11,
734
+ "contentSha1": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
735
+ "contentType": "text/plain",
736
+ "fileId": "9996",
737
+ "fileInfo": {{
738
+ "a": "b"
739
+ }},
740
+ "fileName": "file1_copy.txt",
741
+ "uploadTimestamp": 5003
742
+ }}
743
+ '''
744
+ self ._run_command (
745
+ [
746
+ 'copy_file' ,
747
+ '--metadataDirective' ,
748
+ 'replace' ,
749
+ '--contentType' ,
750
+ 'text/plain' ,
751
+ '--info' ,
752
+ 'a=b' ,
753
+ '9999' ,
754
+ 'my-bucket' ,
755
+ 'file1_copy.txt' ,
756
+ ],
757
+ expected_stdout ,
758
+ '' ,
759
+ 0 ,
760
+ )
761
+
762
+ # UnsatisfiableRange
763
+ expected_stderr = "ERROR: The range in the request is outside the size of the file\n "
764
+ self ._run_command (
765
+ ['copy_file' , '--range' , '12,20' , '9999' , 'my-bucket' , 'file1_copy.txt' ],
766
+ '' ,
767
+ expected_stderr ,
768
+ 1 ,
769
+ )
770
+
771
+ # Copy in different bucket
772
+ self ._run_command (['create_bucket' , 'my-bucket1' , 'allPublic' ], 'bucket_1\n ' , '' , 0 )
773
+ expected_stdout = '''
774
+ {{
775
+ "accountId": "{account_id}",
776
+ "action": "copy",
777
+ "bucketId": "bucket_1",
778
+ "contentLength": 11,
779
+ "contentSha1": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
780
+ "contentType": "b2/x-auto",
781
+ "fileId": "9994",
782
+ "fileInfo": {{
783
+ "src_last_modified_millis": "1500111222000"
784
+ }},
785
+ "fileName": "file1_copy.txt",
786
+ "uploadTimestamp": 5004
787
+ }}
788
+ '''
789
+ self ._run_command (
790
+ ['copy_file' , '9999' , 'my-bucket1' , 'file1_copy.txt' ], expected_stdout , '' , 0
791
+ )
792
+
592
793
def test_get_download_auth_defaults (self ):
593
794
self ._authorize_account ()
594
795
self ._create_my_bucket ()
0 commit comments