-
Notifications
You must be signed in to change notification settings - Fork 44
feat: find tree root via a user-specified command #571
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
Conversation
6d5cb7a
to
36c37db
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's good
e1b66b6
to
32bedf9
Compare
@MattSturgeon, do you mind giving this a review as well? |
7b01ed5
to
10b377b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The concept looks good to me, thanks! I'll defer to @jfly for the more technical review.
shlex
I do wonder about the merit of using shlex vs either requiring that multi-arg commands be configured as a list, or evaluated using a real shell (i.e. bash).
treefmt-nix
Slightly off topic, but I wonder what implications this has for treefmt-nix?
Now that git rev-parse --show-toplevel
is used by default, does that mean that treefmt-nix no longer needs to provide a default for tree-root-file
, projectRootFile
(default ".git/config"
), projectRoot
(default self
1), etc?
Also, how should the change be communicate to users who have gotten in the habit of setting tree-root-file
or projectRootFile
themselves, as that is now likely to be redundant?
Footnotes
-
Tangent: does
projectRoot
's current defaultself
make sense? Since that'll be an in-store path, and won't ever be used anyway becauseprojectRootFile
is always defined ↩
10b377b
to
4e0be6b
Compare
Took another pass and fixed some bad assumptions. Fresh reviews have been requested 🙏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the new determineTreeRoot
function to be way more readable than before, thank you!
8ce083e
to
96a2d04
Compare
Correct. The default root file of
This is a good point. It will be in the release notes, and I can point it out on Fosstodon as well. A Nixos discourse post might also be appropriate? |
618d37f
to
e2067dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
config/config.go
Outdated
if treeRoot == "" { | ||
return "", fmt.Errorf("empty output received after executing tree-root-cmd: %s", cfg.TreeRootCmd) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally would prefer to put this check up a layer in determineTreeRoot
. If somebody explicitly specifies --tree-root ""
, I'd also like them to get this error, rather than having it fall back to the current directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If somebody explicitly specifies
--tree-root " "
I was about to comment that ""
would be treated as tree-root
being undefined, however if a whitespace-only value is defined then you're right, it would run into this edge-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, good point. I didn't remember we're treating "unset" and "set to empty string" as the same thing here.
I still do feel like it would make more sense to do this check as part of the "is this potential root a valid path? let's normalize it" codepath, and not in the implementation of a specific root discovery mechanism.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite following what is being advocated for here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe @jfly is suggesting the new assertion for non-empty (trimmed) stdout could also apply to other methods of setting the tree root.
Currently it is possible to explicitly define tree-root = " "
, which would bypass the tree-root != ""
checks.
IMO this begs the question of whether trimming stdout is the correct approach anyway. If not, this argument would be kinda irrelevant.
However trimming is good enough for an initial implementation, since valid filepaths with leading/trailing whitespace seem very unlikely, and the command printing additional blank lines is rather likely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this begs the question of whether trimming stdout is the correct approach anyway.
In hindsight, I believe the most correct approach here would be to split on \n
, then remove the empty lines.
You can then assert that the remaining line count is 1, and also use the lines slice to log the stdout line-by-line.
lines := strings.Split(stdout, "\n")
nonEmptyLines := slices.DeleteFunc(lines, func(line string) bool {
return line == ""
}
switch (len(nonEmptyLines)) {
case 1:
// no-op
case 0:
return "", fmt.Errorf("empty output received after executing tree-root-cmd: %s", cfg.TreeRootCmd)
default:
// Log all stdout line-by-line, including the blank lines
logger := log.WithPrefix("tree-root-cmd | stdout")
for _, line := range lines {
logger.Error(line)
}
return "", fmt.Errorf("tree-root-cmd cannot output multiple lines: %s", cfg.TreeRootCmd)
}
As said before, trimming is fine for the initial impl, I can open a follow up PR for this if preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All mechanisms must pass through the same stage of realising their output as absolute paths, which should throw an error for any malformed paths. Trimming the output of the command execution and enforcing a single line seems prudent, specifically for the tree-root-cmd
pathway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which should throw an error for any malformed paths
This is the part that bothers me: IIRC, we're using go's built-in Path.abs
to do this, which accepts empty strings rather than erroring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the part that bothers me: IIRC, we're using go's built-in
Path.abs
to do this, which accepts empty strings rather than erroring.
I believe it is impossible to define a truly empty tree-root path; attempting to set tree-root = ""
will be treated as undefined. Returning an empty string from tree-root-cmd
will be caught here.
As for blank/whitespace paths, a whitepace string is technically a valid relative path. On some filesystems you can name a file/dir " "
(if you really wanted to).
This is one reason why the current impl splits stdout into lines, instead of just trimming it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall. Thanks again for working on this!
A few minor things outstanding most of which you probably don't need to block on if you don't want to:
- Docs for how tree-root-cmd is parsed (feat: find tree root via a user-specified command #571 (comment))
- Maybe docs for where tree-root-cmd is run (feat: find tree root via a user-specified command #571 (comment))
- Update docs for
tree-root
's default (feat: find tree root via a user-specified command #571 (comment)) - Maybe also checking the trimmed treeRoot is non-empty for explicit
tree-root
defs (feat: find tree root via a user-specified command #571 (comment)) - Packaging nits
(feat: find tree root via a user-specified command #571 (comment))
(feat: find tree root via a user-specified command #571 (comment)) - A couple more nits below:
e2067dd
to
c6ed5bb
Compare
385c112
to
984050e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to review again with such minor comments... Despite the noise, the PR is looking really good!
config/config.go
Outdated
if treeRoot == "" { | ||
return "", fmt.Errorf("empty output received after executing tree-root-cmd: %s", cfg.TreeRootCmd) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this begs the question of whether trimming stdout is the correct approach anyway.
In hindsight, I believe the most correct approach here would be to split on \n
, then remove the empty lines.
You can then assert that the remaining line count is 1, and also use the lines slice to log the stdout line-by-line.
lines := strings.Split(stdout, "\n")
nonEmptyLines := slices.DeleteFunc(lines, func(line string) bool {
return line == ""
}
switch (len(nonEmptyLines)) {
case 1:
// no-op
case 0:
return "", fmt.Errorf("empty output received after executing tree-root-cmd: %s", cfg.TreeRootCmd)
default:
// Log all stdout line-by-line, including the blank lines
logger := log.WithPrefix("tree-root-cmd | stdout")
for _, line := range lines {
logger.Error(line)
}
return "", fmt.Errorf("tree-root-cmd cannot output multiple lines: %s", cfg.TreeRootCmd)
}
As said before, trimming is fine for the initial impl, I can open a follow up PR for this if preferred.
984050e
to
8633913
Compare
I don't mind, I'd rather get it right. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only things outstanding for me are
- Removing empty lines instead of arbitrarily trimming stdout
(feat: find tree root via a user-specified command #571 (comment)) - Having a test case for git-repo & no defined
tree-root
option
(feat: find tree root via a user-specified command #571 (comment))
Neither of these are blocking IMO, so I approve 🎉
(I haven't tested locally, but the diff & tests all look good)
Signed-off-by: Brian McGee <[email protected]> Co-authored-by: Matt Sturgeon <[email protected]> Signed-off-by: Brian McGee <[email protected]>
4dd85b7
to
b97672a
Compare
Closes #530