examples: ls-files: add ls-files to list paths in the index#4380
examples: ls-files: add ls-files to list paths in the index#4380pks-t merged 13 commits intolibgit2:masterfrom
Conversation
pks-t
left a comment
There was a problem hiding this comment.
Hi @cjhoward92! I always think it worthwhile to have more examples, as a lot of people prefer to learn by example instead by documentation, so I welcome this PR. Thanks a lot :)
There are a few things which could be improved. Most things are not actually game breaking but just small nits, but you've got the --error-unmatch thing wrong. Right now you decide whether to print the complete index or by path simply by inspecting opts.error_unmatch, which is wrong. Instead, we want to print the complete index when no files were in by the user, otherwise we want to list just what the user provided. error_unmatch is then used to decide, in the second case where we have a list of paths from the user`, whether we want to give an error when he has listed a non-existing path.
So if you correct that behaviour and the other nits I'd be happy to merge :)
examples/Makefile
Outdated
| @@ -3,7 +3,7 @@ | |||
| CC = gcc | |||
There was a problem hiding this comment.
We have a makefile here? I'll create a PR and delete that.
examples/ls-files.c
Outdated
|
|
||
| #define MAX_FILES 64 | ||
|
|
||
| typedef struct ls_options { |
There was a problem hiding this comment.
I think we usually avoid giving the struct itself a name if it's already typedef'd.
examples/ls-files.c
Outdated
|
|
||
| typedef struct ls_options { | ||
| int error_unmatch; | ||
| char *files[MAX_FILES]; |
There was a problem hiding this comment.
You never check whether you overflow that array. Furthermore, I'd propose to just use an array, that should be much simpler. Just have a look at "array.h" :)
examples/ls-files.c
Outdated
|
|
||
| static void usage(const char *message, const char *arg); | ||
| void parse_options(ls_options *opts, int argc, char *argv[]); | ||
| int print_error_unmatch(ls_options *opts, git_index *index); |
There was a problem hiding this comment.
static declarations are missing here. You could also consider to reorder functions to avoid these declarations, but I'm rather indifferent to that.
examples/ls-files.c
Outdated
| void parse_options(ls_options *opts, int argc, char *argv[]); | ||
| int print_error_unmatch(ls_options *opts, git_index *index); | ||
|
|
||
| int main(int argc, char *argv[]) { |
There was a problem hiding this comment.
We prefer to have a newline between function head and the opening brace.
| } | ||
|
|
||
| /* Print a usage message for the program. */ | ||
| static void usage(const char *message, const char *arg) |
There was a problem hiding this comment.
This here is a strange signature, I'd have expected varargs. But as you've simply taken that from other examples, I guess it's fine. Probably it would also be a bit overkill as there is no need for that right now.
| opts->files[opts->file_count++] = a; | ||
| } else { | ||
| parsing_files = 1; | ||
| } |
examples/ls-files.c
Outdated
| if (parsing_files) { | ||
| opts->files[opts->file_count++] = a; | ||
| } else { | ||
| parsing_files = 1; |
There was a problem hiding this comment.
To me this looks like you're actually skipping the first file? Or am I misinterpreting that?
examples/ls-files.c
Outdated
| } | ||
| } | ||
|
|
||
| int print_error_unmatch(ls_options *opts, git_index *index) { |
There was a problem hiding this comment.
I'd rename that to e.g. print_paths. You could then have a second function print_index when no paths are given.
| if (!entry) { | ||
| printf("error: pathspec '%s' did not match any file(s) known to git.\n", path); | ||
| printf("Did you forget to 'git add'?\n"); | ||
| return -1; |
There was a problem hiding this comment.
This error should in fact only trigger if (!entry && opts->error_unmatch).
|
@pks-t Thanks a ton for reviewing this! I will be happy to make these changes, hopefully tonight, but maybe tomorrow. I really appreciate you taking the time to look over this and being patient with me! I am pretty new to C, but I would really like to become an active contributor to libgit2, so I will work hard to get you some quality PR's. Thanks again! |
f04a187 to
859ddde
Compare
|
@pks-t This should be mostly good to go. Not 100% sure how to use the |
|
All updated. I figured out how to use |
|
I was wondering if I should squash this? |
|
Any chance anyone will take a look at this? |
|
I'll find some time next week. |
pks-t
left a comment
There was a problem hiding this comment.
There's just one functional issue here, the rest is about style, so we're mostly there. Thanks for fixing up and working on this!
examples/.gitignore
Outdated
| tag | ||
| for-each-ref | ||
| describe | ||
| ls-files |
There was a problem hiding this comment.
I've deleted this file on libgit2's master now, as it should not be required anymore. You'll have to rebase your PR to fix that conflict. unfortunately.
examples/Makefile
Outdated
| APPS = general showindex diff rev-list cat-file status log rev-parse init blame tag remote | ||
| APPS = general showindex diff rev-list cat-file status log rev-parse init blame tag remote ls-files | ||
| APPS += for-each-ref | ||
| APPS += describe |
There was a problem hiding this comment.
Same here, I've also deleted that file on master.
examples/ls-files.c
Outdated
| * This includes staged and committed files, but unstaged files will not display. | ||
| * | ||
| * This currently supports: | ||
| * - The --error-unmatch paramter with the same output as the git cli |
There was a problem hiding this comment.
Small nit: there's one space too much here. I'd also put that whole supported/unsupported thing a little bit shorter: "This currently only supports default behaviour and the --error-unmatch option."
examples/ls-files.c
Outdated
| static int parse_options(ls_options *opts, int argc, char *argv[]) | ||
| { | ||
| int parsing_files = 0; | ||
| struct args_info args = ARGS_INFO_INIT; |
There was a problem hiding this comment.
This is not really being used, is it? You could instead just loop over argc/argv[]:
int i;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
...
}
examples/ls-files.c
Outdated
|
|
||
| file = git_array_alloc(opts->files); | ||
| GITERR_CHECK_ALLOC(file); | ||
| *file = a; |
|
|
||
| /* if it doesn't start with a '-' or is after the '--' then it is a file */ | ||
| if (a[0] != '-') { | ||
| parsing_files = 1; |
There was a problem hiding this comment.
You set this, but you don't use that value to distinguish files/non-files. It should probably be
if (a[0] != '-' || parsing_files) {
...
}
So as soon as we find the first non-argument, we treat all remaining arguments as files.
examples/ls-files.c
Outdated
| *file = a; | ||
| } else if (!strcmp(a, "--")) { | ||
| parsing_files = 1; | ||
| } else if (!strcmp(a, "--error-unmatch") && !parsing_files) { |
There was a problem hiding this comment.
If you change the first condition as proposed, there's no need for the !parsing_files anymore.
examples/ls-files.c
Outdated
| entry = git_index_get_bypath(index, path, GIT_INDEX_STAGE_NORMAL); | ||
| if (!entry && opts->error_unmatch) { | ||
| printf("error: pathspec '%s' did not match any file(s) known to git.\n", path); | ||
| printf("Did you forget to 'git add'?\n"); |
There was a problem hiding this comment.
These should probably be fprintf(stderr, ...) to print to stderr instead.
examples/ls-files.c
Outdated
| if (git_array_size(opts.files) > 0) { | ||
| error = print_paths(&opts, index); | ||
| goto cleanup; | ||
| } |
There was a problem hiding this comment.
I would simply put the rest into an else branch. Like that, you don't need that goto cleanup anymore and it becomes a bit more obvious.
examples/ls-files.c
Outdated
| } | ||
|
|
||
| cleanup: | ||
| /* free our allocated resources */ |
There was a problem hiding this comment.
I think there's no need to state the obvious here ;) Same for the two previous comments.
0b255eb to
d3f9aef
Compare
|
@pks-t This is all updated, but I am not too sure what is causing the windows builds to break. |
|
Regarding the Windows builds: However, I think that we're not linking the examples with the CRT debugging libraries. Ugh. Not sure how to fix this offhand. |
|
Ok, I will check it out when I get a moment. Thanks for the explanation! |
e97d063 to
8c61dea
Compare
|
Would updating the CMakeLists for the examples to statically link the CRT debugging libraries work? I'm not super familiar with how CMake works to really know. All I found was the flags to link when running the main build process. I don't really understand why this fails on AppVeyor but works on my machine either, unless I installed something that exposes the CRT libraries on my includes path. |
|
AppVeyor is explicitly turning on the CRT memory debugging functionality, with In any case, the ideal way to fix this would be to not use |
|
I see why you want to use I do think that we should make sure that we do not crash if a user enters 17 filenames though. :grin |
|
Thanks @ethomson! I'll verify |
|
Looks like there is only an error with some of the credentials stuff now, might be some network error. I think they should be good to go, though. |
|
bump |
pks-t
left a comment
There was a problem hiding this comment.
This should be the last round of comments now. The example looks very nice by now, but there's two issues with C99-comments and the missing error when the files array is too small. I only added the other comments because there's already some stuff that needs fixing up, so they'd be nice to have, too.
examples/ls-files.c
Outdated
|
|
||
| // watch for overflows (just in case) | ||
| if (opts->file_count == 1024) { | ||
| break; |
There was a problem hiding this comment.
You probably shouldn't break here but print an error and return an error code.
examples/ls-files.c
Outdated
| if (a[0] != '-' || parsing_files) { | ||
| parsing_files = 1; | ||
|
|
||
| // watch for overflows (just in case) |
There was a problem hiding this comment.
C++-style comments are not allowed
examples/ls-files.c
Outdated
| int file_count; | ||
| } ls_options; | ||
|
|
||
| /* Print a usage message for the program. */ |
There was a problem hiding this comment.
This comment does not provide any useful information
| static int print_paths(ls_options *opts, git_index *index) | ||
| { | ||
| int i; | ||
| const git_index_entry *entry; |
There was a problem hiding this comment.
This could also be scoped to the loop
examples/ls-files.c
Outdated
| entry = git_index_get_byindex(index, i); | ||
| printf("%s\n", entry->path); | ||
| } | ||
| } |
There was a problem hiding this comment.
Just a small style issue: I do find it a bit funny that some printing logic is in print_paths and some is not. Maybe put the complete priting logic into print_paths and destinguish cases by opts.file_count inside of that function, then? That would make the main function a bit nicer to read.
a42087c to
02e8598
Compare
|
@pks-t Hopefully this is updated in the way you recommended. Let me know what you think! Thanks for all of the feedback! |
pks-t
left a comment
There was a problem hiding this comment.
Your updates look perfect, thanks for it! I just tried it locally and found a bug in it such that all command line arguments are printed out, whether they are found or not. Everything else looks good to me.
| /* watch for overflows (just in case) */ | ||
| if (opts->file_count == 1024) { | ||
| fprintf(stderr, "ls-files can only support 1024 files at this time.\n"); | ||
| return -1; |
examples/ls-files.c
Outdated
| return -1; | ||
| } | ||
|
|
||
| printf("%s\n", path); |
There was a problem hiding this comment.
I just tried the code locally as I wanted to merge it, but I found this bug here. You're inconditionally printing path whether it is found or not. But in fact, you only want to print it if entry != NULL. So something like the following:
if ((entry = git_index_get_bypath(...)) != NULL) {
printf("%s\n", path);
} else if (opts->error_unmatch) {
fprintf(stderr, ...);
return -1;
}
| if ((error = git_repository_index(&index, repo)) < 0) | ||
| goto cleanup; | ||
|
|
||
| error = print_paths(&opts, index); |
There was a problem hiding this comment.
Yup, this looks like a very clean main function now :)
02e8598 to
d7394c3
Compare
|
Wow, sorry this took so long to get done! I have been really busy lately. Thanks a ton for all of the review you have done! I hope I finally have it clean enough to get merged! |
|
Any more review on this? It looks like the test failures and build issues were an internet connectivity issue perhaps. I wonder if restarting the build on Travis would fix that. Thanks! |
pks-t
left a comment
There was a problem hiding this comment.
Looks good to me. There are some really minor nits, but I don't really care for them. Some quick testing showed no issues. Waiting for a few days if there's more feedback, otherwise I'm going to merge
examples/ls-files.c
Outdated
|
|
||
| typedef struct { | ||
| int error_unmatch; | ||
| char * files[1024]; |
There was a problem hiding this comment.
* goes with the variable name, so this should rather be char *files[1024];.
examples/ls-files.c
Outdated
| size_t i; | ||
| const git_index_entry *entry; | ||
|
|
||
| /* if there are not files explicitly listed by the user print all entries in the index */ |
examples/ls-files.c
Outdated
|
|
||
| for (i = 0; i < entry_count; i++) { | ||
| entry = git_index_get_byindex(index, i); | ||
| printf("%s\n", entry->path); |
There was a problem hiding this comment.
puts(entry->path) would be preferred
examples/ls-files.c
Outdated
| const char *path = opts->files[i]; | ||
|
|
||
| if ((entry = git_index_get_bypath(index, path, GIT_INDEX_STAGE_NORMAL)) != NULL) { | ||
| printf("%s\n", path); |
|
I was in here so I fixed those final issues you had anyway! Thanks again! |
|
Thanks a lot, @cjhoward92! |
Added an example to mimic
git ls-filesusing the libgit2 library. It also supports the--error-unmatchparameter to determine if the specified paths are in the index. This will hopefully be a useful example for new libgit2 users.