You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
6.6 KiB

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. -module(rebar_hg_resource).
  4. -behaviour(rebar_resource).
  5. -export([lock/2
  6. ,download/3
  7. ,needs_update/2
  8. ,make_vsn/1]).
  9. -include("rebar.hrl").
  10. lock(AppDir, {hg, Url, _}) ->
  11. lock(AppDir, {hg, Url});
  12. lock(AppDir, {hg, Url}) ->
  13. Ref = get_ref(AppDir),
  14. {hg, Url, {ref, Ref}}.
  15. %% Return `true' if either the hg url or tag/branch/ref is not the same as
  16. %% the currently checked out repo for the dep
  17. needs_update(Dir, {hg, Url, {tag, Tag}}) ->
  18. Ref = get_ref(Dir),
  19. {ClosestTag, Distance} = get_tag_distance(Dir, Ref),
  20. ?DEBUG("Comparing hg tag ~ts with ref ~ts (closest tag is ~ts at distance ~ts)",
  21. [Tag, Ref, ClosestTag, Distance]),
  22. not ((Distance =:= "0") andalso (Tag =:= ClosestTag)
  23. andalso compare_url(Dir, Url));
  24. needs_update(Dir, {hg, Url, {branch, Branch}}) ->
  25. Ref = get_ref(Dir),
  26. BRef = get_branch_ref(Dir, Branch),
  27. not ((Ref =:= BRef) andalso compare_url(Dir, Url));
  28. needs_update(Dir, {hg, Url, "default"}) ->
  29. Ref = get_ref(Dir),
  30. BRef = get_branch_ref(Dir, "default"),
  31. not ((Ref =:= BRef) andalso compare_url(Dir, Url));
  32. needs_update(Dir, {hg, Url, Ref}) ->
  33. LocalRef = get_ref(Dir),
  34. TargetRef = case Ref of
  35. {ref, Ref1} ->
  36. Length = length(LocalRef),
  37. if Length >= 7 -> lists:sublist(Ref1, Length);
  38. Length < 7 -> Ref1
  39. end;
  40. Ref1 ->
  41. Ref1
  42. end,
  43. ?DEBUG("Comparing hg ref ~ts with ~ts", [Ref1, LocalRef]),
  44. not ((LocalRef =:= TargetRef) andalso compare_url(Dir, Url)).
  45. download(Dir, {hg, Url}, State) ->
  46. ?WARN("WARNING: It is recommended to use {branch, Name}, {tag, Tag} or {ref, Ref}, otherwise updating the dep may not work as expected.", []),
  47. download(Dir, {hg, Url, {branch, "default"}}, State);
  48. download(Dir, {hg, Url, ""}, State) ->
  49. ?WARN("WARNING: It is recommended to use {branch, Name}, {tag, Tag} or {ref, Ref}, otherwise updating the dep may not work as expected.", []),
  50. download(Dir, {hg, Url, {branch, "default"}}, State);
  51. download(Dir, {hg, Url, {branch, Branch}}, _State) ->
  52. ok = filelib:ensure_dir(Dir),
  53. maybe_warn_local_url(Url),
  54. rebar_utils:sh(?FMT("hg clone -q -b ~ts ~ts ~ts",
  55. [rebar_utils:escape_chars(Branch),
  56. rebar_utils:escape_chars(Url),
  57. rebar_utils:escape_chars(filename:basename(Dir))]),
  58. [{cd, filename:dirname(Dir)}]);
  59. download(Dir, {hg, Url, {tag, Tag}}, _State) ->
  60. ok = filelib:ensure_dir(Dir),
  61. maybe_warn_local_url(Url),
  62. rebar_utils:sh(?FMT("hg clone -q -u ~ts ~ts ~ts",
  63. [rebar_utils:escape_chars(Tag),
  64. rebar_utils:escape_chars(Url),
  65. rebar_utils:escape_chars(filename:basename(Dir))]),
  66. [{cd, filename:dirname(Dir)}]);
  67. download(Dir, {hg, Url, {ref, Ref}}, _State) ->
  68. ok = filelib:ensure_dir(Dir),
  69. maybe_warn_local_url(Url),
  70. rebar_utils:sh(?FMT("hg clone -q -r ~ts ~ts ~ts",
  71. [rebar_utils:escape_chars(Ref),
  72. rebar_utils:escape_chars(Url),
  73. rebar_utils:escape_chars(filename:basename(Dir))]),
  74. [{cd, filename:dirname(Dir)}]);
  75. download(Dir, {hg, Url, Rev}, _State) ->
  76. ok = filelib:ensure_dir(Dir),
  77. maybe_warn_local_url(Url),
  78. rebar_utils:sh(?FMT("hg clone -q -r ~ts ~ts ~ts",
  79. [rebar_utils:escape_chars(Rev),
  80. rebar_utils:escape_chars(Url),
  81. rebar_utils:escape_chars(filename:basename(Dir))]),
  82. [{cd, filename:dirname(Dir)}]).
  83. make_vsn(Dir) ->
  84. BaseHg = "hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++ "\" ",
  85. Ref = get_ref(Dir),
  86. Cmd = BaseHg ++ "log --template \"{latesttag}+build.{latesttagdistance}.rev.{node|short}\""
  87. " --rev " ++ Ref,
  88. AbortMsg = io_lib:format("Version resolution of hg dependency failed in ~ts", [Dir]),
  89. {ok, VsnString} =
  90. rebar_utils:sh(Cmd,
  91. [{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
  92. RawVsn = rebar_string:trim(VsnString, both, "\n"),
  93. Vsn = case RawVsn of
  94. "null+" ++ Rest -> "0.0.0+" ++ Rest;
  95. _ -> RawVsn
  96. end,
  97. {plain, Vsn}.
  98. %%% Internal functions
  99. compare_url(Dir, Url) ->
  100. CurrentUrl = rebar_string:trim(os:cmd("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++"\" paths default"), both, "\n"),
  101. CurrentUrl1 = rebar_string:trim(CurrentUrl, both, "\r"),
  102. parse_hg_url(CurrentUrl1) =:= parse_hg_url(Url).
  103. get_ref(Dir) ->
  104. AbortMsg = io_lib:format("Get ref of hg dependency failed in ~ts", [Dir]),
  105. {ok, RefString} =
  106. rebar_utils:sh("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++ "\" --debug id -i",
  107. [{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
  108. rebar_string:trim(RefString, both, "\n").
  109. get_tag_distance(Dir, Ref) ->
  110. AbortMsg = io_lib:format("Get tag distance of hg dependency failed in ~ts", [Dir]),
  111. {ok, LogString} =
  112. rebar_utils:sh("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++ "\" "
  113. "log --template \"{latesttag}-{latesttagdistance}\n\" "
  114. "--rev " ++ rebar_utils:escape_chars(Ref),
  115. [{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
  116. Log = rebar_string:trim(LogString,
  117. both, "\n"),
  118. [Tag, Distance] = re:split(Log, "-([0-9]+)$",
  119. [{parts,0}, {return,list}, unicode]),
  120. {Tag, Distance}.
  121. get_branch_ref(Dir, Branch) ->
  122. AbortMsg = io_lib:format("Get branch ref of hg dependency failed in ~ts", [Dir]),
  123. {ok, BranchRefString} =
  124. rebar_utils:sh("hg -R \"" ++ rebar_utils:escape_double_quotes(Dir) ++
  125. "\" log --template \"{node}\n\" --rev " ++ rebar_utils:escape_chars(Branch),
  126. [{use_stdout, false}, {debug_abort_on_error, AbortMsg}]),
  127. rebar_string:strip(BranchRefString, both, "\n").
  128. maybe_warn_local_url(Url) ->
  129. try
  130. _ = parse_hg_url(Url),
  131. ok
  132. catch
  133. _:_ ->
  134. ?WARN("URL format (~ts) unsupported.", [])
  135. end.
  136. parse_hg_url("ssh://" ++ HostPath) ->
  137. [Host | Path] = rebar_string:lexemes(HostPath, "/"),
  138. {Host, filename:rootname(filename:join(Path), ".hg")};
  139. parse_hg_url("http://" ++ HostPath) ->
  140. [Host | Path] = rebar_string:lexemes(HostPath, "/"),
  141. {Host, filename:rootname(filename:join(Path), ".hg")};
  142. parse_hg_url("https://" ++ HostPath) ->
  143. [Host | Path] = rebar_string:lexemes(HostPath, "/"),
  144. {Host, filename:rootname(filename:join(Path), ".hg")}.