Permalink
Please sign in to comment.
Browse files
Merge branch 'ls/p4-lfs'
Teach "git p4" to send large blobs outside the repository by talking to Git LFS. * ls/p4-lfs: git-p4: add Git LFS backend for large file system git-p4: add support for large file systems git-p4: check free space during streaming git-p4: add file streaming progress in verbose mode git-p4: return an empty list if a list config has no values git-p4: add gitConfigInt reader git-p4: add optional type specifier to gitConfig reader
- Loading branch information...
Showing
with
766 additions
and 16 deletions.
- +32 −0 Documentation/git-p4.txt
- +254 −16 git-p4.py
- +192 −0 t/t9823-git-p4-mock-lfs.sh
- +288 −0 t/t9824-git-p4-git-lfs.sh
32
Documentation/git-p4.txt
270
git-p4.py
192
t/t9823-git-p4-mock-lfs.sh
@@ -0,0 +1,192 @@ | ||
+#!/bin/sh | ||
+ | ||
+test_description='Clone repositories and store files in Mock LFS' | ||
+ | ||
+. ./lib-git-p4.sh | ||
+ | ||
+test_file_is_not_in_mock_lfs () { | ||
+ FILE="$1" && | ||
+ CONTENT="$2" && | ||
+ echo "$CONTENT" >expect_content && | ||
+ test_path_is_file "$FILE" && | ||
+ test_cmp expect_content "$FILE" | ||
+} | ||
+ | ||
+test_file_is_in_mock_lfs () { | ||
+ FILE="$1" && | ||
+ CONTENT="$2" && | ||
+ LOCAL_STORAGE=".git/mock-storage/local/$CONTENT" && | ||
+ SERVER_STORAGE=".git/mock-storage/remote/$CONTENT" && | ||
+ echo "pointer-$CONTENT" >expect_pointer && | ||
+ echo "$CONTENT" >expect_content && | ||
+ test_path_is_file "$FILE" && | ||
+ test_path_is_file "$LOCAL_STORAGE" && | ||
+ test_path_is_file "$SERVER_STORAGE" && | ||
+ test_cmp expect_pointer "$FILE" && | ||
+ test_cmp expect_content "$LOCAL_STORAGE" && | ||
+ test_cmp expect_content "$SERVER_STORAGE" | ||
+} | ||
+ | ||
+test_file_is_deleted_in_mock_lfs () { | ||
+ FILE="$1" && | ||
+ CONTENT="$2" && | ||
+ LOCAL_STORAGE=".git/mock-storage/local/$CONTENT" && | ||
+ SERVER_STORAGE=".git/mock-storage/remote/$CONTENT" && | ||
+ echo "pointer-$CONTENT" >expect_pointer && | ||
+ echo "$CONTENT" >expect_content && | ||
+ test_path_is_missing "$FILE" && | ||
+ test_path_is_file "$LOCAL_STORAGE" && | ||
+ test_path_is_file "$SERVER_STORAGE" && | ||
+ test_cmp expect_content "$LOCAL_STORAGE" && | ||
+ test_cmp expect_content "$SERVER_STORAGE" | ||
+} | ||
+ | ||
+test_file_count_in_dir () { | ||
+ DIR="$1" && | ||
+ EXPECTED_COUNT="$2" && | ||
+ find "$DIR" -type f >actual && | ||
+ test_line_count = $EXPECTED_COUNT actual | ||
+} | ||
+ | ||
+test_expect_success 'start p4d' ' | ||
+ start_p4d | ||
+' | ||
+ | ||
+test_expect_success 'Create repo with binary files' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ ( | ||
+ cd "$cli" && | ||
+ | ||
+ echo "content 1 txt 23 bytes" >file1.txt && | ||
+ p4 add file1.txt && | ||
+ echo "content 2-3 bin 25 bytes" >file2.dat && | ||
+ p4 add file2.dat && | ||
+ p4 submit -d "Add text and binary file" && | ||
+ | ||
+ mkdir "path with spaces" && | ||
+ echo "content 2-3 bin 25 bytes" >"path with spaces/file3.bin" && | ||
+ p4 add "path with spaces/file3.bin" && | ||
+ p4 submit -d "Add another binary file with same content and spaces in path" && | ||
+ | ||
+ echo "content 4 bin 26 bytes XX" >file4.bin && | ||
+ p4 add file4.bin && | ||
+ p4 submit -d "Add another binary file with different content" | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in Mock LFS based on size (>24 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem MockLFS && | ||
+ git config git-p4.largeFileThreshold 24 && | ||
+ git config git-p4.largeFilePush True && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" && | ||
+ test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" && | ||
+ test_file_is_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" && | ||
+ test_file_is_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" && | ||
+ | ||
+ test_file_count_in_dir ".git/mock-storage/local" 2 && | ||
+ test_file_count_in_dir ".git/mock-storage/remote" 2 | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in Mock LFS based on extension (dat)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem MockLFS && | ||
+ git config git-p4.largeFileExtensions dat && | ||
+ git config git-p4.largeFilePush True && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" && | ||
+ test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" && | ||
+ test_file_is_not_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" && | ||
+ test_file_is_not_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" && | ||
+ | ||
+ test_file_count_in_dir ".git/mock-storage/local" 1 && | ||
+ test_file_count_in_dir ".git/mock-storage/remote" 1 | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in Mock LFS based on extension (dat) and use git p4 sync and no client spec' ' | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem MockLFS && | ||
+ git config git-p4.largeFileExtensions dat && | ||
+ git config git-p4.largeFilePush True && | ||
+ git p4 sync //depot && | ||
+ git checkout p4/master && | ||
+ | ||
+ test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" && | ||
+ test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" && | ||
+ test_file_is_not_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" && | ||
+ test_file_is_not_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" && | ||
+ | ||
+ test_file_count_in_dir ".git/mock-storage/local" 1 && | ||
+ test_file_count_in_dir ".git/mock-storage/remote" 1 | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Remove file from repo and store files in Mock LFS based on size (>24 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ ( | ||
+ cd "$cli" && | ||
+ p4 delete file4.bin && | ||
+ p4 submit -d "Remove file" | ||
+ ) && | ||
+ | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem MockLFS && | ||
+ git config git-p4.largeFileThreshold 24 && | ||
+ git config git-p4.largeFilePush True && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_is_not_in_mock_lfs file1.txt "content 1 txt 23 bytes" && | ||
+ test_file_is_in_mock_lfs file2.dat "content 2-3 bin 25 bytes" && | ||
+ test_file_is_in_mock_lfs "path with spaces/file3.bin" "content 2-3 bin 25 bytes" && | ||
+ test_file_is_deleted_in_mock_lfs file4.bin "content 4 bin 26 bytes XX" && | ||
+ | ||
+ test_file_count_in_dir ".git/mock-storage/local" 2 && | ||
+ test_file_count_in_dir ".git/mock-storage/remote" 2 | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Run git p4 submit in repo configured with large file system' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem MockLFS && | ||
+ git config git-p4.largeFileThreshold 24 && | ||
+ git config git-p4.largeFilePush True && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_must_fail git p4 submit | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'kill p4d' ' | ||
+ kill_p4d | ||
+' | ||
+ | ||
+test_done |
288
t/t9824-git-p4-git-lfs.sh
@@ -0,0 +1,288 @@ | ||
+#!/bin/sh | ||
+ | ||
+test_description='Clone repositories and store files in Git LFS' | ||
+ | ||
+. ./lib-git-p4.sh | ||
+ | ||
+git lfs help >/dev/null 2>&1 || { | ||
+ skip_all='skipping git p4 Git LFS tests; Git LFS not found' | ||
+ test_done | ||
+} | ||
+ | ||
+test_file_in_lfs () { | ||
+ FILE="$1" && | ||
+ SIZE="$2" && | ||
+ EXPECTED_CONTENT="$3" && | ||
+ cat "$FILE" | grep "size $SIZE" && | ||
+ HASH=$(cat "$FILE" | grep "oid sha256:" | sed -e "s/oid sha256://g") && | ||
+ LFS_FILE=".git/lfs/objects/$(echo "$HASH" | cut -c1-2)/$(echo "$HASH" | cut -c3-4)/$HASH" && | ||
+ echo $EXPECTED_CONTENT >expect && | ||
+ test_path_is_file "$FILE" && | ||
+ test_path_is_file "$LFS_FILE" && | ||
+ test_cmp expect "$LFS_FILE" | ||
+} | ||
+ | ||
+test_file_count_in_dir () { | ||
+ DIR="$1" && | ||
+ EXPECTED_COUNT="$2" && | ||
+ find "$DIR" -type f >actual && | ||
+ test_line_count = $EXPECTED_COUNT actual | ||
+} | ||
+ | ||
+test_expect_success 'start p4d' ' | ||
+ start_p4d | ||
+' | ||
+ | ||
+test_expect_success 'Create repo with binary files' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ ( | ||
+ cd "$cli" && | ||
+ | ||
+ echo "content 1 txt 23 bytes" >file1.txt && | ||
+ p4 add file1.txt && | ||
+ echo "content 2-3 bin 25 bytes" >file2.dat && | ||
+ p4 add file2.dat && | ||
+ p4 submit -d "Add text and binary file" && | ||
+ | ||
+ mkdir "path with spaces" && | ||
+ echo "content 2-3 bin 25 bytes" >"path with spaces/file3.bin" && | ||
+ p4 add "path with spaces/file3.bin" && | ||
+ p4 submit -d "Add another binary file with same content and spaces in path" && | ||
+ | ||
+ echo "content 4 bin 26 bytes XX" >file4.bin && | ||
+ p4 add file4.bin && | ||
+ p4 submit -d "Add another binary file with different content" | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in LFS based on size (>24 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileThreshold 24 && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" && | ||
+ test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" && | ||
+ test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" && | ||
+ | ||
+ test_file_count_in_dir ".git/lfs/objects" 2 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ /file2.dat filter=lfs -text | ||
+ /file4.bin filter=lfs -text | ||
+ /path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in LFS based on size (>25 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileThreshold 25 && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" && | ||
+ test_file_count_in_dir ".git/lfs/objects" 1 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ /file4.bin filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in LFS based on extension (dat)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileExtensions dat && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" && | ||
+ test_file_count_in_dir ".git/lfs/objects" 1 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ *.dat filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Store files in LFS based on size (>25 bytes) and extension (dat)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileExtensions dat && | ||
+ git config git-p4.largeFileThreshold 25 && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" && | ||
+ test_file_in_lfs file4.bin 26 "content 4 bin 26 bytes XX" && | ||
+ test_file_count_in_dir ".git/lfs/objects" 2 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ *.dat filter=lfs -text | ||
+ /file4.bin filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Remove file from repo and store files in LFS based on size (>24 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ ( | ||
+ cd "$cli" && | ||
+ p4 delete file4.bin && | ||
+ p4 submit -d "Remove file" | ||
+ ) && | ||
+ | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileThreshold 24 && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" && | ||
+ test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" && | ||
+ test_path_is_missing file4.bin && | ||
+ test_file_count_in_dir ".git/lfs/objects" 2 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ /file2.dat filter=lfs -text | ||
+ /path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Add .gitattributes and store files in LFS based on size (>24 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ ( | ||
+ cd "$cli" && | ||
+ echo "*.txt text" >.gitattributes && | ||
+ p4 add .gitattributes && | ||
+ p4 submit -d "Add .gitattributes" | ||
+ ) && | ||
+ | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileThreshold 24 && | ||
+ git p4 clone --destination="$git" //depot@all && | ||
+ | ||
+ test_file_in_lfs file2.dat 25 "content 2-3 bin 25 bytes" && | ||
+ test_file_in_lfs "path with spaces/file3.bin" 25 "content 2-3 bin 25 bytes" && | ||
+ test_path_is_missing file4.bin && | ||
+ test_file_count_in_dir ".git/lfs/objects" 2 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ *.txt text | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ /file2.dat filter=lfs -text | ||
+ /path[[:space:]]with[[:space:]]spaces/file3.bin filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'Add big files to repo and store files in LFS based on compressed size (>28 bytes)' ' | ||
+ client_view "//depot/... //client/..." && | ||
+ ( | ||
+ cd "$cli" && | ||
+ echo "content 5 bin 40 bytes XXXXXXXXXXXXXXXX" >file5.bin && | ||
+ p4 add file5.bin && | ||
+ p4 submit -d "Add file with small footprint after compression" && | ||
+ | ||
+ echo "content 6 bin 39 bytes XXXXXYYYYYZZZZZ" >file6.bin && | ||
+ p4 add file6.bin && | ||
+ p4 submit -d "Add file with large footprint after compression" | ||
+ ) && | ||
+ | ||
+ client_view "//depot/... //client/..." && | ||
+ test_when_finished cleanup_git && | ||
+ ( | ||
+ cd "$git" && | ||
+ git init . && | ||
+ git config git-p4.useClientSpec true && | ||
+ git config git-p4.largeFileSystem GitLFS && | ||
+ git config git-p4.largeFileCompressedThreshold 28 && | ||
+ # We only import HEAD here ("@all" is missing!) | ||
+ git p4 clone --destination="$git" //depot && | ||
+ | ||
+ test_file_in_lfs file6.bin 13 "content 6 bin 39 bytes XXXXXYYYYYZZZZZ" | ||
+ test_file_count_in_dir ".git/lfs/objects" 1 && | ||
+ | ||
+ cat >expect <<-\EOF && | ||
+ *.txt text | ||
+ | ||
+ # | ||
+ # Git LFS (see https://git-lfs.github.com/) | ||
+ # | ||
+ /file6.bin filter=lfs -text | ||
+ EOF | ||
+ test_path_is_file .gitattributes && | ||
+ test_cmp expect .gitattributes | ||
+ ) | ||
+' | ||
+ | ||
+test_expect_success 'kill p4d' ' | ||
+ kill_p4d | ||
+' | ||
+ | ||
+test_done |
0 comments on commit
6ff518f