mad_git.erl 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. -module(mad_git).
  2. -compile(export_all).
  3. deps(_Params) ->
  4. case mad_utils:configs() of
  5. {error,E} -> {error,E};
  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,E} -> {error,E};
  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,[]) -> git_clone(Uri,Fast,TrunkPath,"master");
  47. git_clone(Uri,Fast,TrunkPath,Rev) ->
  48. {["git clone --single-branch --no-tags --branch ",Rev," ",Fast,Uri," ",TrunkPath],Rev}.
  49. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache) ->
  50. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache, deep).
  51. fetch_dep(Cwd, Config, ConfigFile, Name, Cmd, Uri, Co, Cache, Deep) ->
  52. TrunkPath = case Cache of
  53. deps_fetch -> filename:join([mad_utils:get_value(deps_dir,Config,"deps"),Name]);
  54. Dir -> filename:join([Dir,get_publisher(Uri),Name]) end,
  55. mad:info("==> dependency: ~p tag: ~p~n", [Uri,Co]),
  56. Fast = case mad_utils:get_value(fetch_depth,Config,1) of
  57. 1 -> " --depth 1 ";
  58. _ -> "" end,
  59. {R,Co1} = case Co of
  60. X when is_list(X) -> git_clone(Uri,Fast,TrunkPath,X);
  61. {_,Rev} -> git_clone(Uri,Fast,TrunkPath,Rev);
  62. Master -> git_clone(Uri,Fast,TrunkPath,Master) end,
  63. % VERBOSE
  64. % mad:info("Fetch: ~s~n",[R]),
  65. FetchStatus = case filelib:is_dir(TrunkPath) of
  66. true -> {skip,0,list_to_binary("Directory "++TrunkPath++" exists.")};
  67. false -> sh:run(lists:concat(R)) end,
  68. case FetchStatus of
  69. {_,0,_} -> put(Name, fetched),
  70. %% check dependencies of the dependency
  71. TrunkConfigFile = filename:join(TrunkPath, ConfigFile),
  72. Conf0 = mad_utils:consult(TrunkConfigFile),
  73. case Conf0 of
  74. {error,E} -> {error,E};
  75. {ok,Conf} ->
  76. Conf1 = mad_utils:script(TrunkConfigFile, Conf, Name),
  77. case Deep of
  78. deep -> fetch(Cwd, Config, ConfigFile, mad_utils:get_value(deps, Conf1, []));
  79. _ -> skip
  80. end,
  81. case Cache of
  82. deps_fetch -> {ok,Name};
  83. CacheDir -> build_dep(Cwd, Config, ConfigFile,
  84. get_publisher(Uri), Name, Cmd, Co1, CacheDir)
  85. end end;
  86. {_,_,FetchError} -> {error,FetchError} end.
  87. %% build dependency based on branch/tag/commit
  88. build_dep(Cwd, Conf, _ConfFile, Publisher, Name, _Cmd, _Co, Dir) ->
  89. TrunkPath = filename:join([Dir, Publisher, Name]),
  90. DepsDir = filename:join([mad_utils:get_value(deps_dir, Conf, ["deps"]),Name]),
  91. sh:run(lists:concat(["cp -r ", TrunkPath, " ", DepsDir])),
  92. ok = file:set_cwd(DepsDir),
  93. ok = file:set_cwd(Cwd),
  94. {ok,Name}.
  95. %% internal
  96. name_and_repo(X) -> mad_utils:name_and_repo(X).
  97. get_publisher(Uri) -> case string:tokens(Uri,"@:/") of
  98. [_Proto,_Server,Publisher|_RepoPath] -> Publisher; _ -> core end.
  99. upd(_,[]) -> {ok,[]};
  100. upd(Config,[F|T]) ->
  101. mad:info("==> up: ~p~n", [F]),
  102. Deps = lists:foldl(fun([App,_,{_,_,{RefHead, RefName}}|_],Acc) ->
  103. case binary:match(list_to_binary(F), atom_to_binary(App,utf8)) of
  104. {Pos, Len} when Pos+Len =:= length(F) -> [{RefHead,RefName}|Acc]; _ -> Acc end;
  105. (_,Acc) -> Acc end, [], [tuple_to_list(D) || D <- mad_utils:get_value(deps, Config, [])]),
  106. {_, Status, Message} = case Deps of
  107. [{tag,"master"}] ->
  108. % many configs marks master as tag even if its incorrect revision to fetch
  109. sh:run(lists:concat(["cd ",F," && git pull origin master && git checkout master && cd -"]));
  110. [{tag,Tag}] ->
  111. sh:run(lists:concat(["cd ",F," && git fetch origin \"+refs/tags/",Tag,":refs/tags/",Tag,"\" && git checkout tags/", Tag," && cd -"]));
  112. [{branch, Branch}] ->
  113. sh:run(lists:concat(["cd ",F," && git pull origin ",Branch," && git checkout ", Branch, " && cd -"]));
  114. _ -> sh:run(lists:concat(["cd ",F," && git pull && cd -"]))
  115. end,
  116. case Status of
  117. 0 -> mad_utils:verbose(Config,Message), upd(Config,T);
  118. _ -> case binary:match(Message,[<<"You are not currently on a branch">>]) of
  119. nomatch -> mad_utils:verbose(Config,Message), {error,Message};
  120. _ -> upd(Config,T) end end.
  121. up(Params) ->
  122. case mad_utils:configs() of
  123. {error,E} -> {error,E};
  124. {ok,{ _Cwd,_ConfigFileName,Config }} ->
  125. List = case Params of
  126. [] -> [ F || F <- mad_repl:wildcards(["deps/*"]), filelib:is_dir(F) ];
  127. Apps -> [ "deps/" ++ A || A <- Apps ] end ++ ["."],
  128. upd(Config,List)
  129. end.