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

Support long file and branch names in checkout conflict creation #4520

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

novalis
Copy link
Contributor

@novalis novalis commented Feb 8, 2018

When we have a conflict, we generate conflict files of the form
filename~branchname, or sometimes filename~branchname_[digits], if
there already exists filename~branchname. When the length of this
would be over NAME_MAX, shorten it by truncating one or more
of the components.

@novalis
Copy link
Contributor Author

novalis commented Mar 6, 2018

(please ignore for a bit, hacking Windows stuff which I can only do through appveyor since I don't run Windows)

@novalis novalis force-pushed the long-names branch 17 times, most recently from 9d2eb71 to fbda733 Compare March 11, 2018 17:50
@novalis novalis force-pushed the long-names branch 4 times, most recently from a1df0e9 to a39c294 Compare March 14, 2018 20:18
@novalis novalis force-pushed the long-names branch 5 times, most recently from f718232 to 6e30306 Compare March 14, 2018 23:11
@novalis
Copy link
Contributor Author

novalis commented Mar 15, 2018

OK, did what I should have done in the first place. Please review.

Copy link
Member

@pks-t pks-t left a comment

Choose a reason for hiding this comment

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

Thanks for working on this. I'll relay the longpath-handling stuff to @ethomson, as I'm not familiar with that on Windows.

I do feel like you should somehow split out that logic to only be used on Windows. On Unix-based systems this is not the right thing to do, I'd argue, but there we should probably just error out. Also, PATH_MAX is usually set to 4096 there, which is much more reasonable than 256.

src/checkout.c Outdated
size_t sequence_len;
char sequence_buf[(CHAR_BIT * sizeof(int) / 3) + 3];

/* Figure out the length of the suffix inclusive of the
Copy link
Member

Choose a reason for hiding this comment

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

We try to use either

/*
 * Foobar
 */

or

/* Foobar */

style comments

src/checkout.c Outdated
size_t basename_len,
const char *suffix,
size_t suffix_len,
int sequence) {
Copy link
Member

Choose a reason for hiding this comment

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

The function-opening brace belongs on the next line

const char *suffix,
size_t suffix_len,
int sequence) {
size_t basename_max = (NAME_MAX * 2) / 3;
Copy link
Member

Choose a reason for hiding this comment

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

A comment explaining this would help a lot

src/checkout.c Outdated
/* Figure out the length of the suffix inclusive of the
* sequence number */
if (sequence != -1) {
/* Would like to use snprintf here, but it's C99 */
Copy link
Member

Choose a reason for hiding this comment

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

We do have p_snprintf

src/checkout.c Outdated
@@ -1966,34 +1966,109 @@ static int conflict_entry_name(
return 0;
}

static int checkout_path_suffixed_0(
Copy link
Member

Choose a reason for hiding this comment

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

The name is a bit awkward. What exactly does this function do that checkout_path_suffixed doesn't?

src/checkout.c Outdated

if ((error = git_buf_putc(path, '~')) < 0 || (error = git_buf_puts(path, suffix)) < 0)
return -1;
git_buf_put(&saved_path, git_buf_cstr(path), git_buf_len(path));
Copy link
Member

Choose a reason for hiding this comment

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

You should probably check for an error here

* follows: filename: 2/3; suffix and digits: 1/3 - 1 (for the
* '~'). But if either filename or suffix doesn't completely
* fill its allotted space, we allow the other to take up the
* slack.
Copy link
Member

Choose a reason for hiding this comment

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

Aren't these (at least partially) implementation details of checkout_path_suffixed_0?

src/checkout.c Outdated

i++;
while (git_path_exists(git_buf_cstr(path)) && i < INT_MAX) {
Copy link
Member

Choose a reason for hiding this comment

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

INT_MAX? I feel like we should restrict this to a sane value, shouldn't we? Checking 2 billion paths hardly feels like the right thing to do

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 don't know what value would be reasonable. Whatever limit we put here, someone could create a situation that fails it. How would you feel if I made it a config value with a default of (say) 10?

Copy link
Member

Choose a reason for hiding this comment

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

I agree. I'd aim a bit higher than 10, though. After lots of back and forth I think that 64 is the correct value.

@@ -50,13 +50,13 @@ struct checkout_index_entry {
uint16_t mode;
char oid_str[GIT_OID_HEXSZ+1];
int stage;
char path[128];
char path[256];
Copy link
Member

Choose a reason for hiding this comment

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

Why don't you just use PATH_MAX here and in the following declarations?

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 these are not actually paths, but filenames. So NAME_MAX + 1 is probably what's wanted.

@novalis
Copy link
Contributor Author

novalis commented Mar 26, 2018

I do feel like you should somehow split out that logic to only be used on Windows. On Unix-based systems this is not the right thing to do, I'd argue, but there we should probably just error out. Also, PATH_MAX is usually set to 4096 there, which is much more reasonable than 256.

I don't understand what you're saying here.

This patch is in fact Unix-only. It doesn't work on Windows because Windows doesn't support long file names without funny shenanigans (see #3053, mentioned in the comments here). We hit this issue on Unix, where we couldn't check out certain files. I would love to fix it for Windows as well, but when I messed around with it, I discovered that I would have to fix #3053 first, and that's a fair amount of work.

@novalis
Copy link
Contributor Author

novalis commented Mar 26, 2018

Other than the INT_MAX thing, I pushed a change for the rest of the requested changes, I think

@pks-t
Copy link
Member

pks-t commented Mar 27, 2018

Sorry, I was confused a bit. Whenever I hear "long" and "file" I actually think about the Windows thing "core.longpath". So please just ignore that bit

When we have a conflict, we generate conflict files of the form
filename~branchname, or sometimes filename~branchname_[digits], if
there already exists filename~branchname.  When the length of this
would be over NAME_MAX, shorten it by truncating one or more
of the components.
@novalis
Copy link
Contributor Author

novalis commented Mar 28, 2018

The Travis build seems to be messed up -- it can't download from Debian. Maybe it needs a kick?

@pks-t
Copy link
Member

pks-t commented Mar 28, 2018

Yeah, Travis is having problems again. I already started kicking some other PRs, but now it's the macOS builds which cannot catch up. I'll give jobs another kick as soon as the queue has been processed

@novalis
Copy link
Contributor Author

novalis commented Apr 11, 2018

Is this ready-to-go?

Base automatically changed from master to main January 7, 2021 10:09
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.

None yet

2 participants