<div dir="ltr">2013/8/19 Idan Kamara <span dir="ltr"><<a href="mailto:idankk86@gmail.com" target="_blank">idankk86@gmail.com</a>></span><br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div><div class="h5">On Mon, Aug 19, 2013 at 7:40 PM, Iulian Stana <span dir="ltr"><<a href="mailto:julian.stana@gmail.com" target="_blank">julian.stana@gmail.com</a>></span> wrote:<br></div></div><div class="gmail_extra">
<div class="gmail_quote"><div><div class="h5">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">2013/8/19 Idan Kamara <span dir="ltr"><<a href="mailto:idankk86@gmail.com" target="_blank">idankk86@gmail.com</a>></span><br>

<div class="gmail_extra"><div><div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


<div dir="ltr"><div><div>On Mon, Aug 19, 2013 at 3:10 PM, Giovanni Gherdovich <span dir="ltr"><<a href="mailto:g.gherdovich@gmail.com" target="_blank">g.gherdovich@gmail.com</a>></span> wrote:<br></div></div>
<div class="gmail_extra"><div class="gmail_quote"><div><div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><br><br><div class="gmail_quote">


<div><div>2013/8/18 Iulian Stana <span dir="ltr"><<a href="mailto:julian.stana@gmail.com" target="_blank">julian.stana@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
# HG changeset patch<br>
# User Iulian Stana <<a href="mailto:julian.stana@gmail.com" target="_blank">julian.stana@gmail.com</a>><br>
# Date 1376828454 -10800<br>
#      Sun Aug 18 15:20:54 2013 +0300<br>
# Node ID 04bf311c99b8f4cf4c3e2096b493ee126f861b99<br>
# Parent  21be7b973803e02b0bb310465691f88705a2dd53<br>
c-hglib: hg_log() level 1 function<br>
<br>
The revision history could have a huge mass of data. To deal with this issue, I<br>
had created a iterator-like mechanism. In this way I will get the changesets in<br>
chunks or more-like one at the time.<br>
<br>
The hg_log function will prepare the command and then will call cmd-server for<br>
changesets. This function will return to the user a iterator structure, to be<br>
used on hg_fetch_log_entry funciton. (The log command will not passing any<br>
changeset to the user)<br>
<br>
The hg_fetch_log_entry function will read changesets from command server and<br>
will pass into the hg_log_entry_t structure in a parse way the changeset.<br>
The hg_log_entry_t structure will be one of the function parameter.<br>
<br>
In the main.c file it can be found an example on how this function can be used.<br>
<br>
diff --git a/client.c b/client.c<br>
new file mode 100644<br>
--- /dev/null<br>
+++ b/client.c<br>
@@ -0,0 +1,134 @@<br>
+#define _GNU_SOURCE<br>
+#include <errno.h><br>
+#include <fcntl.h><br>
+#include <stdlib.h><br>
+#include <stdio.h><br>
+#include <string.h><br>
+#include <unistd.h><br>
+#include <sys/types.h><br>
+#include <sys/wait.h><br>
+#include <signal.h><br>
+<br>
+<br>
+#include "client.h"<br>
+#include "utils.h"<br>
+<br>
+#define HGPATH "hg"<br>
+#define CHANGESET "{rev}\\0{node}\\0{tags}\\0{branch}\\0{author}\\0{desc}\<br>
+                                               \\0{date|isodate}\\0"<br>
+<br>
+/**<br>
+ * \brief A helper for building the command arguments.<br>
+ * \param command The name for mercurial command.<br>
+ * \param options An array pointer to command option list.<br>
+ * \param template Template to be used for this command.<br>
+ * \retval new_string An array of pointers, where the command it's almost ready<br>
+ *                    to be send to mercurial cmdserver.<br>
+ * */<br>
+char **cmdbuilder(char *command, char *options[], char *template)<br>
+{<br>
+       int cmd_size, size;<br>
+       char **new_cmd;<br>
+       char *temp = "--template";<br>
+<br>
+       for(size = 0; options[size] != NULL; size++);<br>
+       cmd_size = size + 1;<br>
+       new_cmd = malloc(sizeof(char *) * (cmd_size + 3));<br>
+<br>
+       new_cmd[0] = command;<br>
+       memcpy(new_cmd + 1, options, (cmd_size - 1)  * sizeof(char *));<br>
+       if(template){<br>
+               new_cmd[cmd_size] = temp;<br>
+               new_cmd[cmd_size + 1] = template;<br>
+               new_cmd[cmd_size + 2] = NULL;<br>
+       }else{<br>
+               new_cmd[cmd_size] = NULL;<br>
+       }<br>
+<br>
+       return new_cmd;<br>
+}<br>
+<br>
+/**<br>
+ * \brief 'Parse a changeset'. It's more like pointing to the correct position.<br>
+ *<br>
+ * The changeset could be found on buff pointer. To not duplicate the data I<br>
+ * choose to point every log_entry field to the right position.<br>
+ * \param buff The pointer to the changeset.<br>
+ * \param le   The log_entry_t structure where the changeset will be parse.<br>
+ * \retval 0 if successful.<br>
+ * */<br>
+int parse_changeset(char *buff, hg_log_entry_t *le)<br>
+{<br>
+       /* set pointer for revision position */<br>
+       le->rev = buff;<br>
+<br>
+       /* set pointer for node position */<br>
+       buff = buff + strlen(buff) + 1;<br>
+       le->node = buff;<br>
+<br>
+       /* set pointer for tag position */<br>
+       buff = buff + strlen(buff) + 1;<br>
+       le->tags = buff;<br>
+<br>
+       /* set pointer for branch position */<br>
+       buff = buff + strlen(buff) + 1;<br>
+       le->branch = buff;<br>
+<br>
+       /* set pointer for author position */<br>
+       buff = buff + strlen(buff) + 1;<br>
+       le->author = buff;<br>
+<br>
+       /* set pointer for description position */<br>
+       buff = buff + strlen(buff) + 1;<br>
+       le->desc = buff;<br>
+<br>
+       /* set pointer for data position */<br>
+       buff = buff + strlen(buff) + 1;<br>
+       le->date = buff;<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+/* The high level log command for hglib API. */<br>
+hg_log_iterator *hg_log(hg_handle *handle, char *option[])<br>
+{<br>
+       hg_log_iterator *log_iterator = malloc(sizeof(hg_log_iterator));<br>
+       log_iterator->handle = handle;<br>
+<br>
+       log_iterator->command = cmdbuilder("log", option, CHANGESET);<br>
+<br>
+       if(hg_rawcommand(handle, log_iterator->command) < 0){<br>
+               return NULL;<br>
+       }<br>
+<br>
+       log_iterator->changeset = malloc(0);<br>
+       return log_iterator;<br></blockquote><div><br></div></div></div><div><br>What happens here is that hg_log() does not return a status code<br>(with the meaning "command successfully sent"), but the hg_log_iterator struct instead.<br>




<br></div><div>A status code would be desirable and idiomatic I think;<br></div><div>the struct to be passed as an argument.<br></div><div><div><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">





+}<br>
+<br>
+/* The iterator next step. Getting the next changeset. */<br>
+int hg_fetch_log_entry(hg_log_iterator *log_iterator, hg_log_entry_t *le)<br>
+{<br>
+       hg_header head = hg_head(log_iterator->handle);<br>
+<br>
+       if(head.channel == 'r'){<br>
+               free(log_iterator->command);<br>
+               free(log_iterator->changeset);<br>
+               int exitcode = hg_exitcode(log_iterator->handle);<br>
+               free(log_iterator);<br>
+               return exitcode;<br>
+       }<br>
+<br>
+       log_iterator->changeset = realloc(log_iterator->changeset, head.length);<br>
+<br>
+       if(read(log_iterator->handle->p_read, log_iterator->changeset,<br>
+                                       head.length) < 0){<br></blockquote><div><br><br></div></div><div>Here you are not using hg_rawread(). Please explain why.<br></div><div>Level 1 functions are meant to build on top of level 0 functions.<br>




<br></div><div>Also: you are not reading in 4096 B chunks.<br></div><div><br></div><div>Also: you are assuming that all information for a given log entry<br></div><div>(a revision) are retrieved in a "single shot" of the  'o' channel.<br>




<br></div><div>You are assuming that a log revision cannot be split across two<br></div><div>iteration of output on the 'o' channel.<br><br></div><div>Is this assumption safe?<br></div></div></div></div></blockquote>



<div><br></div></div></div><div>No.</div></div></div></div>
</blockquote></div><br></div></div>Your answer is not clear... You want to say that the server will </div><div class="gmail_extra">give a revision in more "shots"? From my test I saw that the cmdserver</div><div class="gmail_extra">


will send a log entry in a single call ( when I am using a template) </div><div class="gmail_extra">even if that revision have 20 kB.</div><div class="gmail_extra">The header from cmdserver is something like channel = 'o' length = 20000</div>


<div class="gmail_extra">data = [...] </div></div></blockquote><div><br></div></div></div><div>The command server is oblivious to the data it writes. It simply forwards whatever hg normally writes to stdout, but in the command protocol.</div>

<div>So nothing guarantees what you're seeing, even though that's what happens in practice.<br></div><div class="im"><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir="ltr"><div class="gmail_extra"><div><br></div><div>Or the operation of getting the entire data in one call, is the bad thing?</div></div></div></blockquote><div><br></div></div><div>What data is that? All the output generated by 'hg log ..'? Or the data for one</div>

<div>log entry?</div></div></div></div></blockquote><div><br></div><div>By data I mean a log entry in a call... What I understand from your python-hglib</div><div>implementation, on the hg log command you are doing something similar. In  a </div>
<div>read call from command server you will receive a changeset(a log entry).</div><div>Something like this I am trying to make, getting a changeset in a single call. </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div class="im"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">
<div><br></div><div>Also: If there will be more iterations for a revision, How could I know how </div>

<div>much iterations there are?</div></div></div></blockquote><div><br></div></div><div>Your template defines how to parse the output data. The result channel tells you the current command ended.</div></div></div></div>
</blockquote></div><div class="gmail_extra"><br></div>What I understand from this is that, if you are using such kind of template</div><div class="gmail_extra">the command server will pass a changeset in a single call. </div>
<div class="gmail_extra"><br></div><div class="gmail_extra">What I am trying to ask is what happens if the command server will </div><div class="gmail_extra">send a changeset in 2 calls, or more like if the hg could perform this </div>
<div class="gmail_extra">kind of operation?</div><div class="gmail_extra"><br clear="all"><div><br></div>-- <div dir="ltr"><div>Iulian</div></div>
</div></div>