@@ -583,6 +583,75 @@ static void handle_ref_opt(const char *pattern, const char *prefix)
583
583
clear_ref_exclusion (& ref_excludes );
584
584
}
585
585
586
+ enum format_type {
587
+ /* We would like a relative path. */
588
+ FORMAT_RELATIVE ,
589
+ /* We would like a canonical absolute path. */
590
+ FORMAT_CANONICAL ,
591
+ /* We would like the default behavior. */
592
+ FORMAT_DEFAULT ,
593
+ };
594
+
595
+ enum default_type {
596
+ /* Our default is a relative path. */
597
+ DEFAULT_RELATIVE ,
598
+ /* Our default is a relative path if there's a shared root. */
599
+ DEFAULT_RELATIVE_IF_SHARED ,
600
+ /* Our default is a canonical absolute path. */
601
+ DEFAULT_CANONICAL ,
602
+ /* Our default is not to modify the item. */
603
+ DEFAULT_UNMODIFIED ,
604
+ };
605
+
606
+ static void print_path (const char * path , const char * prefix , enum format_type format , enum default_type def )
607
+ {
608
+ char * cwd = NULL ;
609
+ /*
610
+ * We don't ever produce a relative path if prefix is NULL, so set the
611
+ * prefix to the current directory so that we can produce a relative
612
+ * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
613
+ * we want an absolute path unless the two share a common prefix, so don't
614
+ * set it in that case, since doing so causes a relative path to always
615
+ * be produced if possible.
616
+ */
617
+ if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED ))
618
+ prefix = cwd = xgetcwd ();
619
+ if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED ) {
620
+ puts (path );
621
+ } else if (format == FORMAT_RELATIVE ||
622
+ (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE )) {
623
+ /*
624
+ * In order for relative_path to work as expected, we need to
625
+ * make sure that both paths are absolute paths. If we don't,
626
+ * we can end up with an unexpected absolute path that the user
627
+ * didn't want.
628
+ */
629
+ struct strbuf buf = STRBUF_INIT , realbuf = STRBUF_INIT , prefixbuf = STRBUF_INIT ;
630
+ if (!is_absolute_path (path )) {
631
+ strbuf_realpath_forgiving (& realbuf , path , 1 );
632
+ path = realbuf .buf ;
633
+ }
634
+ if (!is_absolute_path (prefix )) {
635
+ strbuf_realpath_forgiving (& prefixbuf , prefix , 1 );
636
+ prefix = prefixbuf .buf ;
637
+ }
638
+ puts (relative_path (path , prefix , & buf ));
639
+ strbuf_release (& buf );
640
+ strbuf_release (& realbuf );
641
+ strbuf_release (& prefixbuf );
642
+ } else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED ) {
643
+ struct strbuf buf = STRBUF_INIT ;
644
+ puts (relative_path (path , prefix , & buf ));
645
+ strbuf_release (& buf );
646
+ } else {
647
+ struct strbuf buf = STRBUF_INIT ;
648
+ strbuf_realpath_forgiving (& buf , path , 1 );
649
+ puts (buf .buf );
650
+ strbuf_release (& buf );
651
+ }
652
+ free (cwd );
653
+ }
654
+
586
655
int cmd_rev_parse (int argc , const char * * argv , const char * prefix )
587
656
{
588
657
int i , as_is = 0 , verify = 0 , quiet = 0 , revs_count = 0 , type = 0 ;
@@ -596,6 +665,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
596
665
struct strbuf buf = STRBUF_INIT ;
597
666
const int hexsz = the_hash_algo -> hexsz ;
598
667
int seen_end_of_options = 0 ;
668
+ enum format_type format = FORMAT_DEFAULT ;
599
669
600
670
if (argc > 1 && !strcmp ("--parseopt" , argv [1 ]))
601
671
return cmd_parseopt (argc - 1 , argv + 1 , prefix );
@@ -668,8 +738,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
668
738
if (!argv [i + 1 ])
669
739
die ("--git-path requires an argument" );
670
740
strbuf_reset (& buf );
671
- puts (relative_path (git_path ("%s" , argv [i + 1 ]),
672
- prefix , & buf ));
741
+ print_path (git_path ("%s" , argv [i + 1 ]), prefix ,
742
+ format ,
743
+ DEFAULT_RELATIVE_IF_SHARED );
673
744
i ++ ;
674
745
continue ;
675
746
}
@@ -687,6 +758,16 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
687
758
show (arg );
688
759
continue ;
689
760
}
761
+ if (opt_with_value (arg , "--path-format" , & arg )) {
762
+ if (!strcmp (arg , "absolute" )) {
763
+ format = FORMAT_CANONICAL ;
764
+ } else if (!strcmp (arg , "relative" )) {
765
+ format = FORMAT_RELATIVE ;
766
+ } else {
767
+ die ("unknown argument to --path-format: %s" , arg );
768
+ }
769
+ continue ;
770
+ }
690
771
if (!strcmp (arg , "--default" )) {
691
772
def = argv [++ i ];
692
773
if (!def )
@@ -807,15 +888,15 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
807
888
if (!strcmp (arg , "--show-toplevel" )) {
808
889
const char * work_tree = get_git_work_tree ();
809
890
if (work_tree )
810
- puts (work_tree );
891
+ print_path (work_tree , prefix , format , DEFAULT_UNMODIFIED );
811
892
else
812
893
die ("this operation must be run in a work tree" );
813
894
continue ;
814
895
}
815
896
if (!strcmp (arg , "--show-superproject-working-tree" )) {
816
897
struct strbuf superproject = STRBUF_INIT ;
817
898
if (get_superproject_working_tree (& superproject ))
818
- puts (superproject .buf );
899
+ print_path (superproject .buf , prefix , format , DEFAULT_UNMODIFIED );
819
900
strbuf_release (& superproject );
820
901
continue ;
821
902
}
@@ -850,16 +931,18 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
850
931
const char * gitdir = getenv (GIT_DIR_ENVIRONMENT );
851
932
char * cwd ;
852
933
int len ;
934
+ enum format_type wanted = format ;
853
935
if (arg [2 ] == 'g' ) { /* --git-dir */
854
936
if (gitdir ) {
855
- puts (gitdir );
937
+ print_path (gitdir , prefix , format , DEFAULT_UNMODIFIED );
856
938
continue ;
857
939
}
858
940
if (!prefix ) {
859
- puts (".git" );
941
+ print_path (".git" , prefix , format , DEFAULT_UNMODIFIED );
860
942
continue ;
861
943
}
862
944
} else { /* --absolute-git-dir */
945
+ wanted = FORMAT_CANONICAL ;
863
946
if (!gitdir && !prefix )
864
947
gitdir = ".git" ;
865
948
if (gitdir ) {
@@ -872,14 +955,14 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
872
955
}
873
956
cwd = xgetcwd ();
874
957
len = strlen (cwd );
875
- printf ("%s%s.git\n" , cwd , len && cwd [len - 1 ] != '/' ? "/" : "" );
958
+ strbuf_reset (& buf );
959
+ strbuf_addf (& buf , "%s%s.git" , cwd , len && cwd [len - 1 ] != '/' ? "/" : "" );
876
960
free (cwd );
961
+ print_path (buf .buf , prefix , wanted , DEFAULT_CANONICAL );
877
962
continue ;
878
963
}
879
964
if (!strcmp (arg , "--git-common-dir" )) {
880
- strbuf_reset (& buf );
881
- puts (relative_path (get_git_common_dir (),
882
- prefix , & buf ));
965
+ print_path (get_git_common_dir (), prefix , format , DEFAULT_RELATIVE_IF_SHARED );
883
966
continue ;
884
967
}
885
968
if (!strcmp (arg , "--is-inside-git-dir" )) {
@@ -909,8 +992,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
909
992
if (the_index .split_index ) {
910
993
const struct object_id * oid = & the_index .split_index -> base_oid ;
911
994
const char * path = git_path ("sharedindex.%s" , oid_to_hex (oid ));
912
- strbuf_reset (& buf );
913
- puts (relative_path (path , prefix , & buf ));
995
+ print_path (path , prefix , format , DEFAULT_RELATIVE );
914
996
}
915
997
continue ;
916
998
}
0 commit comments