Andreas Stenius avatar Andreas Stenius committed 08cb57b

Reworked parsing log. Works for git too now.

Comments (0)

Files changed (5)

actions/action_zmr_clone_repo.erl

 
 
 clone_repo(TargetId, RepoId, Context) ->
-    Source = mod_zmr:repo_source(RepoId, Context),
-    Target = mod_zmr:repo_path(RepoId, Context),
-    Cmd = mod_zmr:get_cmd(RepoId, Context, 
-			  [clone, 
-			   {"\\$source", Source}, 
-			   {"\\$target", Target}
-			  ]),
+    Source = mod_zmr:get_repo_url(RepoId, Context),
+    Target = mod_zmr:get_repo_path(RepoId, Context),
+    Cmd = mod_zmr:get_scm_cmd(RepoId,
+			      [clone, 
+			       {"\\$source", Source}, 
+			       {"\\$target", Target}
+			      ],
+			      Context),
     Context1 = update_progress(TargetId, [{message, "Cloning repository..."}], Context),
     Result = os:cmd(Cmd),
     ?PRINT(Result),
 %% interface functions
 -export([
 	 init/1,
-	 repo_path/2,
-	 repo_source/2,
-	 get_cmd/3
+	 get_repo_url/2,
+	 get_repo_path/2,
+	 get_scm_cmd/3,
+	 get_scm_tool/2,
+	 get_scm_log_split/2,
+	 get_scm_log_parse/2
 	]).
 
 %% gen_server interface functions
     ok.
 
 
-repo_path(RepoId, Context) ->
+get_repo_url(RepoId, Context) ->
+    m_rsc:p(RepoId, zmr_repository_url, Context).
+
+get_repo_path(RepoId, Context) ->
     z_path:files_subdir(filename:join("zmr_repos", z_convert:to_list(RepoId)), Context).
 
-repo_source(RepoId, Context) ->
-    m_rsc:p(RepoId, zmr_repository_url, Context).
+get_scm_tool(RepoId, Context) ->
+    m_edge:object(RepoId, zmr_repo_scm, 1, Context).
 
-get_cmd(RepoId, Context, [Op|Vars]) when is_atom(Op) ->
+get_scm_log_split(ToolId, Context) ->
+    z_html:unescape(m_rsc:p(ToolId, zmr_log_re_split, Context)).
+
+get_scm_log_parse(ToolId, Context) ->
+    z_html:unescape(m_rsc:p(ToolId, zmr_log_re_parse, Context)).
+
+get_scm_cmd(ToolId, [Op|Vars], Context) when is_atom(Op) ->
     OpProp = case Op of
 		 clone -> zmr_arg_clone;
 		 log -> zmr_arg_log
 	     end,
-    ToolId = m_edge:object(RepoId, zmr_repo_scm, 1, Context),
     OpVal = z_convert:to_list(m_rsc:p(ToolId, OpProp, Context)),
     Args = lists:foldl(fun({From, To}, Arg) -> re:replace(Arg, From, To, [{return, list}]) end,
 		       OpVal,
 		       Vars),
     Exe = z_convert:to_list(m_rsc:p(ToolId, zmr_command, Context)),
-    Cmd = lists:flatten([Exe, " ", Args]),
-    %?PRINT(Cmd),
-    Cmd.
+    lists:flatten([Exe, " ", Args]).
 
-    
+
+
 datamodel() ->
     [
 
 	 {zmr_command, <<"hg">>},
 	 {zmr_arg_clone, <<"clone --noupdate $source $target">>},
 	 {zmr_arg_log, <<"log">>},
-	 {zmr_log_re, <<"">>}
+	 {zmr_log_re_split, <<"\\R\\R">>},
+	 {zmr_log_re_parse, <<"(?m)^(?<key>\\w+):\\s*(?<value>.*)$">>}
 	]},
 
        {zmr_scm_git,
 	 {title, <<"Git (git)">>},
 	 {zmr_command, <<"git">>},
 	 {zmr_arg_clone, <<"clone --no-checkout $source $target">>},
-	 {zmr_arg_log, <<"log">>}
-	 {zmr_log_re, <<"">>}
+	 {zmr_arg_log, <<"log">>},
+	 {zmr_log_re_split, <<"\\R\\s+.*\\R\\R">>},
+	 {zmr_log_re_parse, <<"(?m)^(?<key>\\w+)?:?\\s*(?<value>.*)$">>}
 	]},
 	
-       {zmr_repo,
+       {mod_zmr_repo,
 	zmr_repository,
 	[
 	 {title, <<"mod_zmr">>},
 	 {body, <<"Zotonic Modules Repository (zmr) is a server for hosting releases of zotonic modules.">>},
 	 {zmr_repository_url, <<"https://bitbucket.astekk.se/zmr">>}
 	]}
-%,
-%       {zmr_default_release,
-%	zmr_release,
-%	[
-%	 {title, <<"Default ZMR release (head)">>},
-%	 {zmr_branch, <<"default">>}
-%	]}
       ]},
 
      {edges,
       [
        {zmr_repo, zmr_repo_scm, zmr_scm_hg}
-%,
-%       {zmr_default_release, zmr_module_release, zmr_repo},
-%       {zmr_repo, relation, zmr_default_release},
-%       {zmr_default_release, relation, zmr_repo}
       ]}
 
     ].
 	    end
     end;
 
-m_find_value(log, #m{value={repo, Id}}=M, Context) ->
-    M#m{value={repo_log, get_repo_log(Id, Context)}};
+m_find_value(log, #m{value={repo, Id}}=_M, Context) ->
+%    M#m{value={repo_log, get_repo_log(Id, Context)}};
+    get_repo_log(Id, Context);
 
 m_find_value(exist, #m{value={repo, Id}}, Context) ->
-    filelib:is_dir(mod_zmr:repo_path(Id, Context));
+    filelib:is_dir(mod_zmr:get_repo_path(Id, Context)).
 
-m_find_value(Key, #m{value={repo_log_entry, Entry}}, _Context) ->
+%m_find_value(Key, #m{value={repo_log_entry, Entry}}, _Context) ->
     %?PRINT(Key),
     %?PRINT(Entry),
-    proplists:get_value(Key, Entry).
+%    proplists:get_value(Key, Entry).
 
 
-m_to_list(#m{value={repo_log, Log}}=M, _Context) ->
-    [M#m{value={repo_log_entry, Entry}} || Entry <- Log];
-m_to_list(#m{value={repo_log_entry, Entry}}, _Context) ->
-    Entry;
+%m_to_list(#m{value={repo_log, Log}}=M, _Context) ->
+%    [M#m{value={repo_log_entry, Entry}} || Entry <- Log];
+%m_to_list(#m{value={repo_log_entry, Entry}}, _Context) ->
+%    Entry;
 
 m_to_list(_, _) ->
     undefined.
 
 
 get_repo_log(Id, Context) -> 
-    Repo = mod_zmr:repo_path(Id, Context),
-    Cmd = lists:flatten(["cd ", Repo, " && ", mod_zmr:get_cmd(Id, Context, [log])]),
+    Repo = mod_zmr:get_repo_path(Id, Context),
+    ToolId = mod_zmr:get_scm_tool(Id, Context),
+    {ok, Split} = re:compile(mod_zmr:get_scm_log_split(ToolId, Context)),
+    {ok, Parse} = re:compile(mod_zmr:get_scm_log_parse(ToolId, Context)),
+    Cmd = lists:flatten(["cd ", Repo, " && ", mod_zmr:get_scm_cmd(ToolId, [log], Context)]),
     Output = os:cmd(Cmd),
     %?PRINT(Output),
-    {match, Match} = re:run(Output, "(?m)^(\\w+):\\s*(.*)$|^$", [global, {capture, all_but_first, list}]),
-    match_to_proplist(Match).
+    RawLog = [re:run(Entry, Parse, [global, {capture, [key, value], list}])
+	   || Entry <- re:split(Output, Split, [trim, {return, list}])],
+    rawlog_to_proplists(RawLog).
 
-%%
-% Matches are reversed after this conversion. Use lists:reverse to restore, if needed
 
-match_to_proplist([]) -> [];
-match_to_proplist(Match) -> match_to_proplist(Match, [[]]).
+rawlog_to_proplists([{match, Matches}|Rest]) -> [rawlog_to_proplists(Matches) | rawlog_to_proplists(Rest)];
+rawlog_to_proplists([nomatch|Rest]) -> rawlog_to_proplists(Rest);
+rawlog_to_proplists([[Key, Value]|MatchList]) -> [{fix_key(Key), Value} | rawlog_to_proplists(MatchList)];
+rawlog_to_proplists(_) -> [].
 
-%keeps props in order, but less efficient
-%match_to_proplist([[Key, Value]|MatchList], [H|Acc]) -> match_to_proplist(MatchList, [H++[{Key, Value}]|Acc]);
-% props in reverse order
-match_to_proplist([[Key, Value]|MatchList], [H|Acc]) -> 
-    match_to_proplist(MatchList, 
-		      [
-		       [{z_convert:to_atom(string:to_lower(Key)), Value}|H]
-		       |Acc
-		      ]
-		     );
-
-match_to_proplist([[]], Acc) -> Acc;
-
-% could call lists:reverse here to restore prop order, if needed
-match_to_proplist([[]|MatchList], Acc) -> match_to_proplist(MatchList, [[]|Acc]);
-
-match_to_proplist([], Acc) -> Acc.
-    
-
+fix_key(changeset) -> id;
+fix_key(commit) -> id;
+fix_key([]) -> fix_key(summary);
+fix_key(Key) when is_list(Key) -> fix_key(z_convert:to_atom(string:to_lower(Key)));
+fix_key(Key) when is_atom(Key) -> Key;
+fix_key(Key) -> fix_key(z_convert:to_atom(Key)).

templates/_admin_edit_content.zmr_scm_tool.tpl

 			</div>
 
 			<div class="form-item clearfix">
-				<label for="zmr_log_re">{_ Log Parser (Regular Expression, PCRE) _}</label>
-				<input id="zmr_log_re" type="text" name="zmr_log_re" value="{{ r.zmr_log_re }}" style="width: 80%" />
+				<label for="zmr_log_re_split">{_ Split Log (Regular Expression, PCRE) _}</label>
+				<input id="zmr_log_re_split" type="text" name="zmr_log_re_split" value="{{ r.zmr_log_re_split }}" style="width: 80%" />
+			</div>
+
+			<div class="form-item clearfix">
+				<label for="zmr_log_re_parse">{_ Parse Log Entry (Regular Expression, PCRE) _}</label>
+				<input id="zmr_log_re_parse" type="text" name="zmr_log_re_parse" value="{{ r.zmr_log_re_parse }}" style="width: 80%" />
 			</div>
 
 		</fieldset>

templates/_zmr_log_entry.tpl

 
 {% wire id=#entry
 	type="click" 
-	action={set_value target=target value=entry.changeset} 
+	action={set_value target=target value=entry.id} 
 	action={dialog_close} 
 %}
 <div id={{#entry}}>
-{% autoescape on %}
-	<b>Changeset:</b> {{entry.changeset}}{% if entry.tag %} ({{entry.tag}}){% endif %}<br />
-	<b>Date:</b> {{entry.date}}<br />
-	<b>User:</b> {{entry.user}}<br />
-	<b>Summary:</b> {{entry.summary}}<br />
-{% endautoescape %}
+{% for key, value in entry %}
+	<b>{{key}}:</b> {{value|escape}}<br />
+{% endfor %}
 </div>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.