mad_git.erl 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. -module(mad_git).
  2. -compile(export_all).
  3. deps(_Params) ->
  4. case mad_utils:configs() of
  5. {error, _ } -> {error, <<"rebar.config error">>};
  6. {ok,{ Cwd, ConfigFile, Conf }} ->
  7. case mad_utils:get_value(deps, Conf, []) of
  8. [] -> {ok,[]};
  9. Deps -> file:make_dir(mad_utils:get_value(deps_dir, Conf, ["deps"])),
  10. (mad:profile()):fetch([Cwd, Conf, ConfigFile, Deps]) end end.
  11. fetch([Cwd, Conf, ConfigFile, Deps]) -> fetch(Cwd, Conf, ConfigFile, Deps).
  12. fetch(_, _Config, _, []) -> false;
  13. fetch(Cwd, Config, ConfigFile, [H|T]) when is_tuple(H) =:= false -> fetch(Cwd, Config, ConfigFile, T);
  14. fetch(Cwd, Config, ConfigFile, [H|T]) ->
  15. {Name, Repo} = name_and_repo(H),
  16. Res = case get(Name) of
  17. fetched -> {ok,Name};
  18. _ ->
  19. {Cmd, Uri, Co} = case Repo of
  20. V={_, _, _} -> V;
  21. {_Cmd, _Url, _Co, _} -> {_Cmd, _Url, _Co};
  22. {_Cmd, _Url} -> {_Cmd, _Url, "master"};
  23. Url when is_list(Url) -> {git, Url, "master"}
  24. end,
  25. Cmd1 = atom_to_list(Cmd),
  26. Cache = mad_utils:get_value(cache, Config, deps_fetch),
  27. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd1, Uri, Co, Cache)
  28. end,
  29. case Res of
  30. {error,E} -> {error,E};
  31. {ok,_} -> fetch(Cwd, Config, ConfigFile, T) end.
  32. get_repo([]) -> {error,"Repository unspecified."};
  33. get_repo([Name|_]) ->
  34. case mad_utils:configs() of
  35. {error,_} -> {error,<<"rebar.config error while retriving deps">>};
  36. {ok,{ Cwd, File, Conf }} ->
  37. Res = case string:tokens(Name,"/") of
  38. [Org, Rep] -> {ok,Rep,lists:concat(["https://github.com/",Org,"/",Rep])};
  39. [Rep] -> {ok,Rep,lists:concat(["https://github.com/synrc/",Rep])};
  40. [] -> {error,"Repository invalid."}
  41. end,
  42. case Res of
  43. {error,X} -> {error,X};
  44. {ok,N,Uri} -> fetch_dep(Cwd,Conf,File,N,"git",Uri,[],deps_fetch,[])
  45. end end.
  46. git_clone(Uri,Fast,TrunkPath,Rev) when Rev == "head" orelse Rev == "HEAD"
  47. orelse Rev == "master" orelse Rev == [] ->
  48. {["git clone ",Fast,Uri," ",TrunkPath],Rev};
  49. git_clone(Uri,_Fast,TrunkPath,Rev) ->
  50. {["git clone ",Uri," ",TrunkPath,
  51. " && cd ",TrunkPath,
  52. " && git checkout \"",Rev,"\"" ],Rev}.
  53. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache) ->
  54. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache, deep).
  55. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache, Deep) ->
  56. TrunkPath = case Cache of
  57. deps_fetch -> filename:join([mad_utils:get_value(deps_dir,Config,"deps"),Name]);
  58. Dir -> filename:join([Dir,get_publisher(Uri),Name]) end,
  59. mad:info("==> dependency: ~p tag: ~p~n", [Uri,Co]),
  60. Fast = case mad_utils:get_value(fetch_speed,Config,[]) of
  61. fast_master -> " --depth=1 ";
  62. _ -> "" end,
  63. {R,Co1} = case Co of
  64. X when is_list(X) -> git_clone(Uri,Fast,TrunkPath,X);
  65. {_,Rev} -> git_clone(Uri,Fast,TrunkPath,Rev);
  66. Master -> git_clone(Uri,Fast,TrunkPath,Master) end,
  67. %mad:info("Fetch: ~s~n",[R]),
  68. FetchStatus = case filelib:is_dir(TrunkPath) of
  69. true -> {skip,0,list_to_binary("Directory "++TrunkPath++" exists.")};
  70. false -> sh:run(lists:concat(R)) end,
  71. case FetchStatus of
  72. {_,0,_} -> put(Name, fetched),
  73. %% check dependencies of the dependency
  74. TrunkConfigFile = filename:join(TrunkPath, ConfigFile),
  75. Conf0 = mad_utils:consult(TrunkConfigFile),
  76. case Conf0 of
  77. {error,_} -> {error, <<"rebar.config error">>};
  78. {ok,Conf} ->
  79. Conf1 = mad_utils:script(TrunkConfigFile, Conf, Name),
  80. case Deep of
  81. deep -> fetch(Cwd, Config, ConfigFile, mad_utils:get_value(deps, Conf1, []));
  82. _ -> skip
  83. end,
  84. case Cache of
  85. deps_fetch -> {ok,Name};
  86. CacheDir -> build_dep(Cwd, Config, ConfigFile,
  87. get_publisher(Uri), Name, Cmd, Co1, CacheDir)
  88. end end;
  89. {_,_,FetchError} -> {error,FetchError} end.
  90. %% build dependency based on branch/tag/commit
  91. build_dep(Cwd, Conf, _ConfFile, Publisher, Name, _Cmd, _Co, Dir) ->
  92. TrunkPath = filename:join([Dir, Publisher, Name]),
  93. DepsDir = filename:join([mad_utils:get_value(deps_dir, Conf, ["deps"]),Name]),
  94. sh:run(lists:concat(["cp -r ", TrunkPath, " ", DepsDir])),
  95. ok = file:set_cwd(DepsDir),
  96. ok = file:set_cwd(Cwd),
  97. {ok,Name}.
  98. %% internal
  99. name_and_repo(X) -> mad_utils:name_and_repo(X).
  100. get_publisher(Uri) -> case string:tokens(Uri,"@:/") of
  101. [_Proto,_Server,Publisher|_RepoPath] -> Publisher; _ -> core end.
  102. upd(_,[]) -> {ok,[]};
  103. upd(Config,[F|T]) ->
  104. mad:info("==> up: ~p~n", [F]),
  105. Deps = lists:foldl(fun([App,_,{_,_,{RefHead, RefName}}|_],Acc) ->
  106. case binary:match(list_to_binary(F), atom_to_binary(App,utf8)) of
  107. {Pos, Len} when Pos+Len =:= length(F) -> [{RefHead,RefName}|Acc]; _ -> Acc end;
  108. (_,Acc) -> Acc end, [], [tuple_to_list(D) || D <- mad_utils:get_value(deps, Config, [])]),
  109. {_, Status, Message} = case Deps of
  110. [{tag,"master"}] ->
  111. % many configs marks master as tag even if its incorrect revision to fetch
  112. sh:run(lists:concat(["cd ",F," && git pull origin master && git checkout master && cd -"]));
  113. [{tag,Tag}] ->
  114. sh:run(lists:concat(["cd ",F," && git fetch origin \"+refs/tags/",Tag,":refs/tags/",Tag,"\" && git checkout tags/", Tag," && cd -"]));
  115. [{branch, Branch}] ->
  116. sh:run(lists:concat(["cd ",F," && git pull origin ",Branch," && git checkout ", Branch, " && cd -"]));
  117. _ -> sh:run(lists:concat(["cd ",F," && git pull && cd -"]))
  118. end,
  119. case Status of
  120. 0 -> mad_utils:verbose(Config,Message), upd(Config,T);
  121. _ -> case binary:match(Message,[<<"You are not currently on a branch">>]) of
  122. nomatch -> mad_utils:verbose(Config,Message), {error,Message};
  123. _ -> upd(Config,T) end end.
  124. up(Params) ->
  125. case mad_utils:configs() of
  126. {error,_} -> {error,<<"rebar.config error while up.">>};
  127. { _Cwd,_ConfigFileName,Config } ->
  128. List = case Params of
  129. [] -> [ F || F <- mad_repl:wildcards(["deps/*"]), filelib:is_dir(F) ];
  130. Apps -> [ "deps/" ++ A || A <- Apps ] end ++ ["."],
  131. upd(Config,List)
  132. end.