@@ -50,6 +50,20 @@ static char *get_default_remote(void)
50
50
return ret ;
51
51
}
52
52
53
+ static int print_default_remote (int argc , const char * * argv , const char * prefix )
54
+ {
55
+ const char * remote ;
56
+
57
+ if (argc != 1 )
58
+ die (_ ("submodule--helper print-default-remote takes no arguments" ));
59
+
60
+ remote = get_default_remote ();
61
+ if (remote )
62
+ printf ("%s\n" , remote );
63
+
64
+ return 0 ;
65
+ }
66
+
53
67
static int starts_with_dot_slash (const char * str )
54
68
{
55
69
return str [0 ] == '.' && is_dir_sep (str [1 ]);
@@ -358,6 +372,25 @@ static void module_list_active(struct module_list *list)
358
372
* list = active_modules ;
359
373
}
360
374
375
+ static char * get_up_path (const char * path )
376
+ {
377
+ int i ;
378
+ struct strbuf sb = STRBUF_INIT ;
379
+
380
+ for (i = count_slashes (path ); i ; i -- )
381
+ strbuf_addstr (& sb , "../" );
382
+
383
+ /*
384
+ * Check if 'path' ends with slash or not
385
+ * for having the same output for dir/sub_dir
386
+ * and dir/sub_dir/
387
+ */
388
+ if (!is_dir_sep (path [strlen (path ) - 1 ]))
389
+ strbuf_addstr (& sb , "../" );
390
+
391
+ return strbuf_detach (& sb , NULL );
392
+ }
393
+
361
394
static int module_list (int argc , const char * * argv , const char * prefix )
362
395
{
363
396
int i ;
@@ -718,6 +751,164 @@ static int module_name(int argc, const char **argv, const char *prefix)
718
751
return 0 ;
719
752
}
720
753
754
+ struct sync_cb {
755
+ const char * prefix ;
756
+ unsigned int flags ;
757
+ };
758
+
759
+ #define SYNC_CB_INIT { NULL, 0 }
760
+
761
+ static void sync_submodule (const char * path , const char * prefix ,
762
+ unsigned int flags )
763
+ {
764
+ const struct submodule * sub ;
765
+ char * remote_key = NULL ;
766
+ char * sub_origin_url , * super_config_url , * displaypath ;
767
+ struct strbuf sb = STRBUF_INIT ;
768
+ struct child_process cp = CHILD_PROCESS_INIT ;
769
+ char * sub_config_path = NULL ;
770
+
771
+ if (!is_submodule_active (the_repository , path ))
772
+ return ;
773
+
774
+ sub = submodule_from_path (& null_oid , path );
775
+
776
+ if (sub && sub -> url ) {
777
+ if (starts_with_dot_dot_slash (sub -> url ) ||
778
+ starts_with_dot_slash (sub -> url )) {
779
+ char * remote_url , * up_path ;
780
+ char * remote = get_default_remote ();
781
+ strbuf_addf (& sb , "remote.%s.url" , remote );
782
+
783
+ if (git_config_get_string (sb .buf , & remote_url ))
784
+ remote_url = xgetcwd ();
785
+
786
+ up_path = get_up_path (path );
787
+ sub_origin_url = relative_url (remote_url , sub -> url , up_path );
788
+ super_config_url = relative_url (remote_url , sub -> url , NULL );
789
+
790
+ free (remote );
791
+ free (up_path );
792
+ free (remote_url );
793
+ } else {
794
+ sub_origin_url = xstrdup (sub -> url );
795
+ super_config_url = xstrdup (sub -> url );
796
+ }
797
+ } else {
798
+ sub_origin_url = xstrdup ("" );
799
+ super_config_url = xstrdup ("" );
800
+ }
801
+
802
+ displaypath = get_submodule_displaypath (path , prefix );
803
+
804
+ if (!(flags & OPT_QUIET ))
805
+ printf (_ ("Synchronizing submodule url for '%s'\n" ),
806
+ displaypath );
807
+
808
+ strbuf_reset (& sb );
809
+ strbuf_addf (& sb , "submodule.%s.url" , sub -> name );
810
+ if (git_config_set_gently (sb .buf , super_config_url ))
811
+ die (_ ("failed to register url for submodule path '%s'" ),
812
+ displaypath );
813
+
814
+ if (!is_submodule_populated_gently (path , NULL ))
815
+ goto cleanup ;
816
+
817
+ prepare_submodule_repo_env (& cp .env_array );
818
+ cp .git_cmd = 1 ;
819
+ cp .dir = path ;
820
+ argv_array_pushl (& cp .args , "submodule--helper" ,
821
+ "print-default-remote" , NULL );
822
+
823
+ strbuf_reset (& sb );
824
+ if (capture_command (& cp , & sb , 0 ))
825
+ die (_ ("failed to get the default remote for submodule '%s'" ),
826
+ path );
827
+
828
+ strbuf_strip_suffix (& sb , "\n" );
829
+ remote_key = xstrfmt ("remote.%s.url" , sb .buf );
830
+
831
+ strbuf_reset (& sb );
832
+ submodule_to_gitdir (& sb , path );
833
+ strbuf_addstr (& sb , "/config" );
834
+
835
+ if (git_config_set_in_file_gently (sb .buf , remote_key , sub_origin_url ))
836
+ die (_ ("failed to update remote for submodule '%s'" ),
837
+ path );
838
+
839
+ if (flags & OPT_RECURSIVE ) {
840
+ struct child_process cpr = CHILD_PROCESS_INIT ;
841
+
842
+ cpr .git_cmd = 1 ;
843
+ cpr .dir = path ;
844
+ prepare_submodule_repo_env (& cpr .env_array );
845
+
846
+ argv_array_push (& cpr .args , "--super-prefix" );
847
+ argv_array_pushf (& cpr .args , "%s/" , displaypath );
848
+ argv_array_pushl (& cpr .args , "submodule--helper" , "sync" ,
849
+ "--recursive" , NULL );
850
+
851
+ if (flags & OPT_QUIET )
852
+ argv_array_push (& cpr .args , "--quiet" );
853
+
854
+ if (run_command (& cpr ))
855
+ die (_ ("failed to recurse into submodule '%s'" ),
856
+ path );
857
+ }
858
+
859
+ cleanup :
860
+ free (super_config_url );
861
+ free (sub_origin_url );
862
+ strbuf_release (& sb );
863
+ free (remote_key );
864
+ free (displaypath );
865
+ free (sub_config_path );
866
+ }
867
+
868
+ static void sync_submodule_cb (const struct cache_entry * list_item , void * cb_data )
869
+ {
870
+ struct sync_cb * info = cb_data ;
871
+ sync_submodule (list_item -> name , info -> prefix , info -> flags );
872
+
873
+ }
874
+
875
+ static int module_sync (int argc , const char * * argv , const char * prefix )
876
+ {
877
+ struct sync_cb info = SYNC_CB_INIT ;
878
+ struct pathspec pathspec ;
879
+ struct module_list list = MODULE_LIST_INIT ;
880
+ int quiet = 0 ;
881
+ int recursive = 0 ;
882
+
883
+ struct option module_sync_options [] = {
884
+ OPT__QUIET (& quiet , N_ ("Suppress output of synchronizing submodule url" )),
885
+ OPT_BOOL (0 , "recursive" , & recursive ,
886
+ N_ ("Recurse into nested submodules" )),
887
+ OPT_END ()
888
+ };
889
+
890
+ const char * const git_submodule_helper_usage [] = {
891
+ N_ ("git submodule--helper sync [--quiet] [--recursive] [<path>]" ),
892
+ NULL
893
+ };
894
+
895
+ argc = parse_options (argc , argv , prefix , module_sync_options ,
896
+ git_submodule_helper_usage , 0 );
897
+
898
+ if (module_list_compute (argc , argv , prefix , & pathspec , & list ) < 0 )
899
+ return 1 ;
900
+
901
+ info .prefix = prefix ;
902
+ if (quiet )
903
+ info .flags |= OPT_QUIET ;
904
+ if (recursive )
905
+ info .flags |= OPT_RECURSIVE ;
906
+
907
+ for_each_listed_submodule (& list , sync_submodule_cb , & info );
908
+
909
+ return 0 ;
910
+ }
911
+
721
912
static int clone_submodule (const char * path , const char * gitdir , const char * url ,
722
913
const char * depth , struct string_list * reference ,
723
914
int quiet , int progress )
@@ -1498,6 +1689,8 @@ static struct cmd_struct commands[] = {
1498
1689
{"resolve-relative-url-test" , resolve_relative_url_test , 0 },
1499
1690
{"init" , module_init , SUPPORT_SUPER_PREFIX },
1500
1691
{"status" , module_status , SUPPORT_SUPER_PREFIX },
1692
+ {"print-default-remote" , print_default_remote , 0 },
1693
+ {"sync" , module_sync , SUPPORT_SUPER_PREFIX },
1501
1694
{"remote-branch" , resolve_remote_submodule_branch , 0 },
1502
1695
{"push-check" , push_check , 0 },
1503
1696
{"absorb-git-dirs" , absorb_git_dirs , SUPPORT_SUPER_PREFIX },
0 commit comments