Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pull not symlinking new and renamed files #219

Merged
merged 1 commit into from
Nov 30, 2023

Conversation

yut23
Copy link
Contributor

@yut23 yut23 commented Oct 20, 2023

This PR reworks the way pull checks for new files for symlinking, which was broken before due to a missing $ in front of the arithmetic expansion. This made it resolve to HEAD instead of HEAD@{1.seconds.ago}.
It now creates a temporary tag in each castle before running git pull, and diffs against that in symlink_new_files. It also wasn't checking for renamed files, but that's easily fixed with --diff-filter=AR.

This should be much more robust than the previous time-based method, which broke intermittently in my local tests and once during actual use. If $now == $T_START and the current second increments between $now and the git diff call, then HEAD@{1.seconds.ago} will point to the pull itself rather than the commit before it.

I've also added a whole bunch of tests covering all the error conditions and edge cases I could think of.

@andsens
Copy link
Owner

andsens commented Oct 20, 2023

Welcome @yut23. Now those are some high quality PRs right there. Thank you very much.
Now I'm wondering why I never just saved the current HEAD commit sha and compared against that though. I'm guessing it was too much bookkeeping when you are pulling multiple castles🤔 ...

The one issue I see is that something goes wrong between the tag creation and deletion, resulting in the check failing later on because of an internal rather than external conflict. No matter how you look at it though, this actually makes things work better than before. So I'm inclined to just merge it unless you want to address that issue first?

@yut23
Copy link
Contributor Author

yut23 commented Oct 20, 2023

I originally wrote this code 2 years ago (!), and have been using it in my personal fork since then. I was thinking about that potential issue too, but I've never run into it, so it's probably not a huge problem.

@yut23 yut23 closed this Oct 20, 2023
@yut23 yut23 reopened this Oct 20, 2023
@yut23 yut23 force-pushed the fix-pull-symlinking branch from 5e1d206 to 8004dc1 Compare October 20, 2023 15:20
@yut23
Copy link
Contributor Author

yut23 commented Oct 20, 2023

OK, I've figured out how the tag gets cleaned up. pull is run inside a subshell in bin/homeshick, so err will just exit from that subshell. As long as the exit code isn't EX_USAGE, symlink_cloned_files will always be run, and the first thing it does is parse the tag and delete it.

I think this could fail if the user pulls two repos, the second of which already has the tag. This would make pull return EX_USAGE, and the tag in the first repo wouldn't be deleted. I'll see if I can write a test for that. Returning EX_DATAERR instead of EX_USAGE should fix it, and probably makes a bit more sense.

@yut23
Copy link
Contributor Author

yut23 commented Oct 20, 2023

Hmm, that doesn't work. It looks like I was returning EX_USAGE specifically so symlink_cloned_files wouldn't delete a user-created tag.

@yut23 yut23 force-pushed the fix-pull-symlinking branch 2 times, most recently from 3883daf to 951cbe5 Compare October 22, 2023 05:25
Copy link
Owner

@andsens andsens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments. Looks really great though! That's some excellent work on the tests.

lib/commands/pull.sh Show resolved Hide resolved
local now
now=$(date +%s)
if ! git_out=$(cd "$repo" && git diff --name-only --diff-filter=A "HEAD@{(($now-$T_START+1)).seconds.ago}" HEAD -- home 2>/dev/null | wc -l 2>&1); then
if ! git_out=$(cd "$repo" && git diff --name-only --diff-filter=AR "$before_pull" HEAD -- home 2>/dev/null | wc -l 2>&1); then
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just diff to the tag and then delete it after? It's one less command that can go wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was to make sure the tag still gets deleted in case $repo/home isn't a directory, but it looks like we can just move that check after the diff.

lib/commands/pull.sh Outdated Show resolved Hide resolved
@yut23
Copy link
Contributor Author

yut23 commented Oct 25, 2023

I've also got an alternate implementation in https://github.com/yut23/homeshick/tree/fix-pull-symlinking-old, which checks the git hash before and after calling pull in bin/homeshick and only calls symlink_new_files on the repos that changed. I thought the tag method was more elegant initially, but it does introduce more edge cases and error handling.

pull creates a temporary tag in each castle before running git pull, and
uses it to determine which files have been added (and renamed) in
symlink_new_files, which also deletes it.
@yut23 yut23 force-pushed the fix-pull-symlinking branch from 951cbe5 to bed4cfb Compare October 26, 2023 20:54
@andsens
Copy link
Owner

andsens commented Nov 21, 2023

*ping. Do you think this is ready or would you like some more time to work on the PR?

@yut23
Copy link
Contributor Author

yut23 commented Nov 21, 2023

I think it's ready. I've been using it for a while now with no issues.

@andsens andsens merged commit 2cb82d1 into andsens:development Nov 30, 2023
14 checks passed
@yut23 yut23 deleted the fix-pull-symlinking branch November 30, 2023 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants