Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

160 rader
6.6 KiB

  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:trim(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")}.