2121 *
2222 * `git ls-files` base command shows all paths in the index at that time.
2323 * This includes staged and committed files, but unstaged files will not display.
24+ *
25+ * This currently supports:
26+ * - The --error-unmatch paramter with the same output as the git cli
27+ * - default ls-files behavior
28+ *
29+ * This currently does not support:
30+ * - anything else
31+ *
2432 */
2533
2634#define MAX_FILES 64
@@ -31,7 +39,9 @@ typedef struct ls_options {
3139 int file_count ;
3240} ls_options ;
3341
42+ static void usage (const char * message , const char * arg );
3443void parse_options (ls_options * opts , int argc , char * argv []);
44+ int print_error_unmatch (ls_options * opts , git_index * index );
3545
3646int main (int argc , char * argv []) {
3747 ls_options opts ;
@@ -55,16 +65,9 @@ int main(int argc, char *argv[]) {
5565 if ((error = git_repository_index (& index , repo )) != 0 )
5666 goto cleanup ;
5767
68+ /* if the error_unmatch flag is set, we need to print it differently */
5869 if (opts .error_unmatch ) {
59- for (i = 0 ; i < opts .file_count ; i ++ ) {
60- const char * path = opts .files [i ];
61- printf ("Checking first path '%s'\n" , path );
62- entry = git_index_get_bypath (index , path , GIT_INDEX_STAGE_NORMAL );
63- if (!entry ) {
64- printf ("Could not find path '%s'\n" , path );
65- return -1 ;
66- }
67- }
70+ error = print_error_unmatch (& opts , index );
6871 goto cleanup ;
6972 }
7073
@@ -88,9 +91,19 @@ int main(int argc, char *argv[]) {
8891 return error ;
8992}
9093
94+ /* Print a usage message for the program. */
95+ static void usage (const char * message , const char * arg )
96+ {
97+ if (message && arg )
98+ fprintf (stderr , "%s: %s\n" , message , arg );
99+ else if (message )
100+ fprintf (stderr , "%s\n" , message );
101+ fprintf (stderr , "usage: ls-files [--error-unmatch] [--] [<file>...]\n" );
102+ exit (1 );
103+ }
104+
91105void parse_options (ls_options * opts , int argc , char * argv []) {
92106 int parsing_files = 0 ;
93- int file_idx = 0 ;
94107 struct args_info args = ARGS_INFO_INIT ;
95108
96109 memset (opts , 0 , sizeof (ls_options ));
@@ -103,9 +116,9 @@ void parse_options(ls_options *opts, int argc, char *argv[]) {
103116 for (args .pos = 1 ; args .pos < argc ; ++ args .pos ) {
104117 char * a = argv [args .pos ];
105118
119+ /* if it doesn't start with a '-' or is after the '--' then it is a file */
106120 if (a [0 ] != '-' || !strcmp (a , "--" )) {
107121 if (parsing_files ) {
108- printf ("%s\n" , a );
109122 opts -> files [opts -> file_count ++ ] = a ;
110123 } else {
111124 parsing_files = 1 ;
@@ -114,13 +127,27 @@ void parse_options(ls_options *opts, int argc, char *argv[]) {
114127 opts -> error_unmatch = 1 ;
115128 parsing_files = 1 ;
116129 } else {
117- printf ( "Bad command\n" );
130+ usage ( "Unsupported argument" , a );
118131 }
119132 }
133+ }
120134
121- printf ( "file count: %d\n" , opts -> file_count );
135+ int print_error_unmatch ( ls_options * opts , git_index * index ) {
122136 int i ;
137+ const git_index_entry * entry ;
138+
139+ /* loop through the files found in the args and print them if they exist */
123140 for (i = 0 ; i < opts -> file_count ; i ++ ) {
124- printf ("Path ids %d: %s\n" , i , opts -> files [i ]);
141+ const char * path = opts -> files [i ];
142+
143+ entry = git_index_get_bypath (index , path , GIT_INDEX_STAGE_NORMAL );
144+ if (!entry ) {
145+ printf ("error: pathspec '%s' did not match any file(s) known to git.\n" , path );
146+ printf ("Did you forget to 'git add'?\n" );
147+ return -1 ;
148+ }
149+
150+ printf ("%s\n" , path );
125151 }
126- }
152+ return 0 ;
153+ }
0 commit comments