diff --git a/README.md b/README.md index abd9a70..87e3095 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ values in the dictionary after filters have been run are used to create the git commit. ``` -file_data = {'filename':filename,'file_ctx':file_ctx,'d':d} +file_data = {'filename':filename,'file_ctx':file_ctx,'data':file_contents} def file_data_filter(self,file_data): ``` @@ -189,6 +189,11 @@ can be modified by any filter. `file_ctx` is the filecontext from the mercurial python library. After all filters have been run, the values are used to add the file to the git commit. +The `file_data_filter` method is also called when files are deleted, +but in this case the `data` and `file_ctx` keys map to None. This is +so that a filter which modifies file names can apply the same name +transformations when files are deleted. + Submodules ---------- See README-SUBMODULES.md for how to convert subrepositories into git diff --git a/hg-fast-export.py b/hg-fast-export.py index 4877d03..fcd5600 100755 --- a/hg-fast-export.py +++ b/hg-fast-export.py @@ -311,9 +311,18 @@ def export_commit(ui,repo,revision,old_marks,max,count,authors, % (branch, type.encode(), revision + 1, max, len(modified), len(removed)) ) - for filename in removed: + for file in removed: if fn_encoding: - filename=filename.decode(fn_encoding).encode('utf8') + filename=file.decode(fn_encoding).encode('utf8') + else: + filename=file + + if plugins and plugins['file_data_filters']: + file_data = {'filename':filename, 'file_ctx':None, 'data':None} + for filter in plugins['file_data_filters']: + filter(file_data) + filename=file_data['filename'] + filename=strip_leading_slash(filename) if filename==b'.hgsub': remove_gitmodules(ctx) diff --git a/t/file_data_filter.expected b/t/file_data_filter.expected new file mode 100644 index 0000000..722ce6d --- /dev/null +++ b/t/file_data_filter.expected @@ -0,0 +1,27 @@ +blob +mark :1 +data 7 +a_file + +blob +mark :2 +data 17 +a_file_to_rename + +reset refs/heads/master +commit refs/heads/master +mark :3 +author Grevious Bodily Harmsworth 1679014800 +0000 +committer Grevious Bodily Harmsworth 1679014800 +0000 +data 2 +r0M 100644 :1 a.txt +M 100644 :2 c.txt + +commit refs/heads/master +mark :4 +author Grevious Bodily Harmsworth 1679018400 +0000 +committer Grevious Bodily Harmsworth 1679018400 +0000 +data 2 +r1from :3 +D c.txt + diff --git a/t/file_data_filter.t b/t/file_data_filter.t new file mode 100755 index 0000000..a938e97 --- /dev/null +++ b/t/file_data_filter.t @@ -0,0 +1,81 @@ +#!/bin/bash +# +# Copyright (c) 2023 Felipe Contreras +# Copyright (c) 2023 Frej Drejhammar +# +# Check that the file_data_filter is called for removed files. +# + +test_description='Smoke test' + +. "${SHARNESS_TEST_SRCDIR-$(dirname "$0")/sharness}"/sharness.sh || exit 1 + +check() { + echo "$3" > expected && + git -C "$1" show -q --format='%s' "$2" > actual && + test_cmp expected actual +} + +git_create() { + git init -q "$1" +} + +git_convert() { + ( + cd "$2" && + hg-fast-export.sh --repo "../$1" \ + -s --hgtags -n \ + --plugin ../../plugins/rename_file_test_plugin + ) +} + +setup() { + cat > "$HOME"/.hgrc <<-EOF + [ui] + username = Grevious Bodily Harmsworth + EOF +} + +commit0() { + ( + cd hgrepo && + echo "a_file" > a.txt && + echo "a_file_to_rename" > b.txt && + hg add a.txt b.txt && + hg commit -d "2023-03-17 01:00Z" -m "r0" + ) +} + +commit1() { + ( + cd hgrepo && + hg remove b.txt && + hg commit -d "2023-03-17 02:00Z" -m "r1" + ) +} +make-branch() { + hg branch "$1" + FILE=$(echo "$1" | sha1sum | cut -d " " -f 1) + echo "$1" > $FILE + hg add $FILE + hg commit -d "2023-03-17 $2:00Z" -m "Added file in branch $1" +} + +setup + +test_expect_success 'all in one' ' + test_when_finished "rm -rf hgrepo gitrepo" && + + ( + hg init hgrepo && + commit0 && + commit1 + ) && + git_create gitrepo && + git_convert hgrepo gitrepo && + git -C gitrepo fast-export --all > actual && + + test_cmp "$SHARNESS_TEST_DIRECTORY"/file_data_filter.expected actual +' + +test_done diff --git a/t/plugins/rename_file_test_plugin/__init__.py b/t/plugins/rename_file_test_plugin/__init__.py new file mode 100644 index 0000000..7c0e09c --- /dev/null +++ b/t/plugins/rename_file_test_plugin/__init__.py @@ -0,0 +1,15 @@ +import subprocess +import shlex +import sys +from mercurial import node + +def build_filter(args): + return Filter(args) + +class Filter: + def __init__(self, args): + self.filter_contents = shlex.split(args) + + def file_data_filter(self,file_data): + if file_data['filename'] == b'b.txt': + file_data['filename'] = b'c.txt'