33#include "lockfile.h"
44#include "commit.h"
55#include "tag.h"
6+ #include "blob.h"
67#include "refs.h"
78#include "builtin.h"
89#include "exec_cmd.h"
1213#include "hashmap.h"
1314#include "argv-array.h"
1415#include "run-command.h"
16+ #include "revision.h"
17+ #include "list-objects.h"
1518
1619#define MAX_TAGS (FLAG_BITS - 1)
1720
@@ -256,7 +259,7 @@ static unsigned long finish_depth_computation(
256259 return seen_commits ;
257260}
258261
259- static void display_name (struct commit_name * n )
262+ static void append_name (struct commit_name * n , struct strbuf * dst )
260263{
261264 if (n -> prio == 2 && !n -> tag ) {
262265 n -> tag = lookup_tag (& n -> oid );
@@ -272,19 +275,18 @@ static void display_name(struct commit_name *n)
272275 }
273276
274277 if (n -> tag )
275- printf ( "%s" , n -> tag -> tag );
278+ strbuf_addstr ( dst , n -> tag -> tag );
276279 else
277- printf ( "%s" , n -> path );
280+ strbuf_addstr ( dst , n -> path );
278281}
279282
280- static void show_suffix (int depth , const struct object_id * oid )
283+ static void append_suffix (int depth , const struct object_id * oid , struct strbuf * dst )
281284{
282- printf ( "-%d-g%s" , depth , find_unique_abbrev (oid -> hash , abbrev ));
285+ strbuf_addf ( dst , "-%d-g%s" , depth , find_unique_abbrev (oid -> hash , abbrev ));
283286}
284287
285- static void describe ( const char * arg , int last_one )
288+ static void describe_commit ( struct object_id * oid , struct strbuf * dst )
286289{
287- struct object_id oid ;
288290 struct commit * cmit , * gave_up_on = NULL ;
289291 struct commit_list * list ;
290292 struct commit_name * n ;
@@ -293,30 +295,25 @@ static void describe(const char *arg, int last_one)
293295 unsigned long seen_commits = 0 ;
294296 unsigned int unannotated_cnt = 0 ;
295297
296- if (get_oid (arg , & oid ))
297- die (_ ("Not a valid object name %s" ), arg );
298- cmit = lookup_commit_reference (& oid );
299- if (!cmit )
300- die (_ ("%s is not a valid '%s' object" ), arg , commit_type );
298+ cmit = lookup_commit_reference (oid );
301299
302300 n = find_commit_name (& cmit -> object .oid );
303301 if (n && (tags || all || n -> prio == 2 )) {
304302 /*
305303 * Exact match to an existing ref.
306304 */
307- display_name ( n );
305+ append_name ( n , dst );
308306 if (longformat )
309- show_suffix (0 , n -> tag ? & n -> tag -> tagged -> oid : & oid );
307+ append_suffix (0 , n -> tag ? & n -> tag -> tagged -> oid : oid , dst );
310308 if (suffix )
311- printf ("%s" , suffix );
312- printf ("\n" );
309+ strbuf_addstr (dst , suffix );
313310 return ;
314311 }
315312
316313 if (!max_candidates )
317314 die (_ ("no tag exactly matches '%s'" ), oid_to_hex (& cmit -> object .oid ));
318315 if (debug )
319- fprintf (stderr , _ ("searching to describe %s \n" ), arg );
316+ fprintf (stderr , _ ("No exact match on refs or tags, searching to describe\n" ));
320317
321318 if (!have_util ) {
322319 struct hashmap_iter iter ;
@@ -381,22 +378,21 @@ static void describe(const char *arg, int last_one)
381378 }
382379
383380 if (!match_cnt ) {
384- struct object_id * oid = & cmit -> object .oid ;
381+ struct object_id * cmit_oid = & cmit -> object .oid ;
385382 if (always ) {
386- printf ( "%s" , find_unique_abbrev (oid -> hash , abbrev ));
383+ strbuf_addstr ( dst , find_unique_abbrev (cmit_oid -> hash , abbrev ));
387384 if (suffix )
388- printf ("%s" , suffix );
389- printf ("\n" );
385+ strbuf_addstr (dst , suffix );
390386 return ;
391387 }
392388 if (unannotated_cnt )
393389 die (_ ("No annotated tags can describe '%s'.\n"
394390 "However, there were unannotated tags: try --tags." ),
395- oid_to_hex (oid ));
391+ oid_to_hex (cmit_oid ));
396392 else
397393 die (_ ("No tags can describe '%s'.\n"
398394 "Try --always, or create some tags." ),
399- oid_to_hex (oid ));
395+ oid_to_hex (cmit_oid ));
400396 }
401397
402398 QSORT (all_matches , match_cnt , compare_pt );
@@ -434,15 +430,86 @@ static void describe(const char *arg, int last_one)
434430 }
435431 }
436432
437- display_name (all_matches [0 ].name );
433+ append_name (all_matches [0 ].name , dst );
438434 if (abbrev )
439- show_suffix (all_matches [0 ].depth , & cmit -> object .oid );
435+ append_suffix (all_matches [0 ].depth , & cmit -> object .oid , dst );
440436 if (suffix )
441- printf ("%s" , suffix );
442- printf ("\n" );
437+ strbuf_addstr (dst , suffix );
438+ }
439+
440+ struct process_commit_data {
441+ struct object_id current_commit ;
442+ struct object_id looking_for ;
443+ struct strbuf * dst ;
444+ struct rev_info * revs ;
445+ };
446+
447+ static void process_commit (struct commit * commit , void * data )
448+ {
449+ struct process_commit_data * pcd = data ;
450+ pcd -> current_commit = commit -> object .oid ;
451+ }
452+
453+ static void process_object (struct object * obj , const char * path , void * data )
454+ {
455+ struct process_commit_data * pcd = data ;
456+
457+ if (!oidcmp (& pcd -> looking_for , & obj -> oid ) && !pcd -> dst -> len ) {
458+ reset_revision_walk ();
459+ describe_commit (& pcd -> current_commit , pcd -> dst );
460+ strbuf_addf (pcd -> dst , ":%s" , path );
461+ free_commit_list (pcd -> revs -> commits );
462+ pcd -> revs -> commits = NULL ;
463+ }
464+ }
465+
466+ static void describe_blob (struct object_id oid , struct strbuf * dst )
467+ {
468+ struct rev_info revs ;
469+ struct argv_array args = ARGV_ARRAY_INIT ;
470+ struct process_commit_data pcd = { null_oid , oid , dst , & revs };
471+
472+ argv_array_pushl (& args , "internal: The first arg is not parsed" ,
473+ "--objects" , "--in-commit-order" , "--reverse" , "HEAD" ,
474+ NULL );
475+
476+ init_revisions (& revs , NULL );
477+ if (setup_revisions (args .argc , args .argv , & revs , NULL ) > 1 )
478+ BUG ("setup_revisions could not handle all args?" );
479+
480+ if (prepare_revision_walk (& revs ))
481+ die ("revision walk setup failed" );
482+
483+ traverse_commit_list (& revs , process_commit , process_object , & pcd );
484+ reset_revision_walk ();
485+ }
486+
487+ static void describe (const char * arg , int last_one )
488+ {
489+ struct object_id oid ;
490+ struct commit * cmit ;
491+ struct strbuf sb = STRBUF_INIT ;
492+
493+ if (debug )
494+ fprintf (stderr , _ ("describe %s\n" ), arg );
495+
496+ if (get_oid (arg , & oid ))
497+ die (_ ("Not a valid object name %s" ), arg );
498+ cmit = lookup_commit_reference_gently (& oid , 1 );
499+
500+ if (cmit )
501+ describe_commit (& oid , & sb );
502+ else if (lookup_blob (& oid ))
503+ describe_blob (oid , & sb );
504+ else
505+ die (_ ("%s is neither a commit nor blob" ), arg );
506+
507+ puts (sb .buf );
443508
444509 if (!last_one )
445510 clear_commit_marks (cmit , -1 );
511+
512+ strbuf_release (& sb );
446513}
447514
448515int cmd_describe (int argc , const char * * argv , const char * prefix )
0 commit comments