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

Attempted workaround for git worktree issue #965

Merged
merged 1 commit into from
Oct 13, 2021

Conversation

hakanai
Copy link
Contributor

@hakanai hakanai commented Oct 11, 2021

If the directory found as the git dir contains a file called gitdir, attempts to resolve it to find the actual git directory.

(Not quite sure how to unit test because it's not like I can use JGit to create a worktree for the test given that it doesn't support the feature!)

For issue #75 or my issue #964

@nedtwigg
Copy link
Member

It looks to me like this works for git ratchet. But it looks like it probably doesn't work for GitAttributesLineEndings.

  1. Have you integration tested this PR on your own use-case?
  2. Does your Spotless config set the line endings manually, or does it use the default policy (which is GitAttributesLineEndings)

@hakanai
Copy link
Contributor Author

hakanai commented Oct 12, 2021

It looks to me like this works for git ratchet. But it looks like it probably doesn't work for GitAttributesLineEndings.

  1. Have you integration tested this PR on your own use-case?
  2. Does your Spotless config set the line endings manually, or does it use the default policy (which is GitAttributesLineEndings)

Ah, we do set the line endings manually to UNIX (as a workaround for some other issue), so I guess that's why it was enough for us.

The code in GitAttributesLineEndings looks quite different to the code I was modifying in the other class. I guess the two should be sharing this code somehow, but figuring out how to fit it in might take a while.

@nedtwigg
Copy link
Member

figuring out how to fit it in might take a while.

I'd love a PR which figures it out. But I'm also happy to merge this PR as-is if the changelog makes clear that git worktrees are fixed only for ratchetFrom, and they are not fixed for the default lineEndigs GIT_ATTRIBUTES.

@hakanai
Copy link
Contributor Author

hakanai commented Oct 12, 2021

What it appears has happened is, getDotGitDir was originally introduced to work around another similar edge case, submodules - but the same workaround wasn't performed in GitAttributesLineEndings at the same time.

So there's this createRepo method in GitRatchet which has both these workarounds now:

	static Repository createRepo(File dir) throws IOException {
		return FileRepositoryBuilder.create(getDotGitDir(dir, Constants.DOT_GIT));
	}

But in GitAttributesLineEndings, there is instead:

			FileRepositoryBuilder builder = new FileRepositoryBuilder();
			builder.findGitDir(projectDir);

which is using the library itself to find the git directory (I'm guessing that what builder.getGitDir() returns is the same .git directory?) Looking inside the findGitDir method it appears that it may already support some of this correctly, because I can see it reading .git as a file and then parsing it for the gitdir: ... string.

So it might be that replacing this logic somehow with a call to createRepo would be the fix for the latter (we'd move it to a utility class nearby so that both can use the same thing) but it's a bit interesting because the latter only uses the builder and never seems to create the actual Repository object, so I'm not quite sure how to make the two work in the same way.

Maybe we just move getDotGitDir to a utility class and then call that from both?

@nedtwigg
Copy link
Member

Sounds great!

@hakanai
Copy link
Contributor Author

hakanai commented Oct 13, 2021

Working at it but it is a bit of a mess because GitRatchet is generic so that the logic can look at the parent project, but then GitAttributesLineEndings doesn't care whether a parent project exists at all, which is a bit inconsistent. I wanna say a better design might have been to wrap the project object in an adapter so that the same adapter can just be used everywhere, but I can't currently see how everything fits together.

@hakanai
Copy link
Contributor Author

hakanai commented Oct 13, 2021

OK, I did some investigation around JGit's FileRepositoryBuilder to see exactly what results it was getting, and what I seem to find is that it supports submodules correctly but just not worktrees. So I can simplify things somewhat by letting it do most of the work and then applying the workaround for the one case where it doesn't work:

	static File getDotGitDir(File projectDir) {
		FileRepositoryBuilder builder = new FileRepositoryBuilder();
		builder.findGitDir(projectDir);
		return resolveRealGitDirIfWorktreeDir(builder.getGitDir());
	}

And then the workaround:

	static File resolveRealGitDirIfWorktreeDir(File dir) {
		File pointerFile = new File(dir, "gitdir");
		if (pointerFile.isFile()) {
			try {
				String content = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8).trim();
				return new File(content);
			} catch (IOException e) {
				System.err.println("failed to parse git meta: " + e.getMessage());
				return dir;
			}
		} else {
			return dir;
		}
	}

And that method is also what GitAttributesLineEndings needs to do for its case, so I can share a little more code this way.

Unifies logic in `GitRatchet` and `GitAttributesLineEndings` for finding the `.git` directory, into a new `GitWorkarounds` class, so both of these can now have the same workaround code for dealing with JGit not supporting worktrees.

The actual workaround works by using `FileRepositoryBuilder` to find what it thinks is the `.git` directory, and then looking inside that to see if it contains a file called `gitdir`, which indicates the location of the true `.git` directory in the case of a git worktree.

For issue diffplug#75 or my issue diffplug#964
@nedtwigg nedtwigg merged commit 9c5edf8 into diffplug:main Oct 13, 2021
@nedtwigg
Copy link
Member

Amazing!

@nedtwigg
Copy link
Member

Published in plugin-gradle 5.17.0 and plugin-maven 2.17.1

klaren added a commit to klaren/spotless that referenced this pull request Feb 4, 2022
Git supports using the same local repository for multiple checked-out worktrees. JGit does not fully support this, so we have to do some workarounds for it to work.

The previous workaround provided by diffplug#965 did not take `commondir` into consideration, which is the location of a few files.

More details are available at: https://git-scm.com/docs/git-worktree#_details
klaren added a commit to klaren/spotless that referenced this pull request Feb 4, 2022
Git supports using the same local repository for multiple checked-out worktrees. JGit does not fully support this, so we have to do some workarounds for it to work.

The previous workaround provided by diffplug#965 did not take `commondir` into consideration, which is the location of a few files.
klaren added a commit to klaren/spotless that referenced this pull request Feb 4, 2022
Git supports using the same local repository for multiple checked-out worktrees. JGit does not fully support this, so we have to do some workarounds for it to work.

The previous workaround provided by diffplug#965 did not take `commondir` into consideration, which is the location of a few files.
klaren added a commit to klaren/spotless that referenced this pull request Feb 4, 2022
Git supports using the same local repository for multiple checked-out worktrees. JGit does not fully support this, so we have to do some workarounds for it to work.

The previous workaround provided by diffplug#965 did not take `commondir` into consideration, which is the location of a few files.
klaren added a commit to klaren/spotless that referenced this pull request Feb 4, 2022
Git supports using the same local repository for multiple checked-out worktrees. JGit does not fully support this, so we have to do some workarounds for it to work.

The previous workaround provided by diffplug#965 did not take `commondir` into consideration, which is the location of a few files.
@klaren klaren mentioned this pull request Feb 4, 2022
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