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