Patchwork [51,of,55,RFC,c-hglib:level1] hg_tip: creating a high level function for mercurial tip command

login
register
mail settings
Submitter Iulian Stana
Date Sept. 14, 2013, 12:36 a.m.
Message ID <a2dcea1199e87d6687af.1379118963@doppler>
Download mbox | patch
Permalink /patch/2495/
State Deferred, archived
Headers show

Comments

Iulian Stana - Sept. 14, 2013, 12:36 a.m.
# HG changeset patch
# User Iulian Stana <julian.stana@gmail.com>
# Date 1379118287 -10800
#      Sat Sep 14 03:24:47 2013 +0300
# Node ID a2dcea1199e87d6687af9883ee8a00accb65e7bf
# Parent  3e3b964c17ed8e117717dce8ae090976e9b6cc16
hg_tip: creating a high level function for mercurial tip command
Idan Kamara - Sept. 14, 2013, 9:38 a.m.
On Sat, Sep 14, 2013 at 3:36 AM, Iulian Stana <julian.stana@gmail.com>wrote:

> # HG changeset patch
> # User Iulian Stana <julian.stana@gmail.com>
> # Date 1379118287 -10800
> #      Sat Sep 14 03:24:47 2013 +0300
> # Node ID a2dcea1199e87d6687af9883ee8a00accb65e7bf
> # Parent  3e3b964c17ed8e117717dce8ae090976e9b6cc16
> hg_tip: creating a high level function for mercurial tip command
>

Just picking a random patch here, I haven't followed closely..


>
> diff --git a/client.c b/client.c
> --- a/client.c
> +++ b/client.c
> @@ -1393,6 +1393,28 @@
>         return lbuf;
>  }
>
> +/* The high level tip command for hglib API. */
> +hg_cset_entry *hg_tip(hg_handle *handle, int(*callback)(const char *msg,
> +                                               size_t len), char
> *argument[])

+{
> +       int exitcode;
> +       char **command = cmdbuilder("tip", argument , "--template",
> CHANGESET,
> +                                                       NULL);
> +
> +       if(hg_rawcommand(handle, command) < 0){
> +               return NULL;
> +       }
> +       free(command);
> +       exitcode = hg_runcommand(handle, callback, NULL);
> +       if(exitcode != 0)
> +               return NULL;
> +
> +       hg_cset_entry *tip = malloc(sizeof(hg_cset_entry));
> +       parse_changeset(handle->out_data + 1, tip);

+
> +       return tip;
> +}
> +
>  /* The yield next step. Getting the next entry. */
>  int hg_fetch_entry(hg_stream_buffer *stream, int (*detect_byte)(char
> *buff,
>                         int buf_size, int data_on_pipe), int func_type)
> diff --git a/client.h b/client.h
> --- a/client.h
> +++ b/client.h
> @@ -2173,7 +2173,38 @@
>  hg_linestream_buffer *hg_tags(hg_handle *handle, int(*callback)
>                         (const char *msg, size_t len));
>
> -
> +/**
> + * \brief hg_tip command for hglib API.
> + *
> + * The tip revision (usually just called the tip) is the changeset most
> recently
> + * added to the repository (and therefore the most recently changed head).
> + *
> + * If you have just made a commit, that commit will be the tip. If you
> have just
> + * pulled changes from another repository, the tip of that repository
> becomes
> + * the current tip. The "tip" tag is special and cannot be renamed or
> assigned
> + * to a different changeset.
> + *
> + * Options/Argument list option:
> + *
> + *     -p, --patch     show patch
> + *     -g, --git               use git extended diff format
> + *     --style         display using template map file
> + *     --template              display with template
> + *
> + * \param handle The handle of the connection, wherewith I want to
> communicate
> + * \param callback A function that will handle error data.
> + *                 A NULL pointer will ignore error data.
>

What meaningful thing can a user do in this callback?


> + * \param argument The option list. Will contain all option that you wish.
>

If you let the user pass in more arguments, it has the potential of:

1) breaking your changeset parser (user passed --template)
2) leaving unparsed data after you successfully parsed the changeset (not
sure how you deal with that)

I'm not sure you really want that.


> + * \retval cset The command return succesful, with a parse data.
>

hg tip always returns a single changeset, wouldn't it be nicer if you
received a pointer
to hg_cset_entry and wrote the result there, rather than allocating one
inside?


> + * \retval NULL  The command failed.
> + *
> + * errno can be:
> + *      - hg_rawcommand errors
> + *
> + * */
> +hg_cset_entry *hg_tip(hg_handle *handle, int(*callback)(const char *msg,
> +                                               size_t len), char
> *argument[]);
> +
>  /**
>   * \brief The yield mechanism that will get the next entry.
>   *
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
Iulian Stana - Sept. 14, 2013, 12:34 p.m.
> + *
>> + * \param handle The handle of the connection, wherewith I want to
>> communicate
>> + * \param callback A function that will handle error data.
>> + *                 A NULL pointer will ignore error data.
>>
>
> What meaningful thing can a user do in this callback?
>
>

What ever he wants to do with error data, print it do the stderr, store in
some place
or I don't know parse this data in his own way is his decision.



> + * \param argument The option list. Will contain all option that you wish.
>>
>
> If you let the user pass in more arguments, it has the potential of:
>
> 1) breaking your changeset parser (user passed --template)
> 2) leaving unparsed data after you successfully parsed the changeset (not
> sure how you deal with that)
>
>
The last --template will overwrite all preview templates probably I must
tell in
documentation that is not allowed to use other template...

hg tip --template '{rev}' --template '{node}' --template 'Template - {rev}
- {node}\n'

I'm not sure you really want that.
>

I really don't want to leave unparse data.


>
>
>> + * \retval cset The command return succesful, with a parse data.
>>
>
> hg tip always returns a single changeset, wouldn't it be nicer if you
> received a pointer
> to hg_cset_entry and wrote the result there, rather than allocating one
> inside?
>

Probably, I don't know:) I thought that it would be nice to return a
cset_entry and
to give user less work to do :) But this thing can be easy changed.


>
>
>> + * \retval NULL  The command failed.
>> + *
>> + * errno can be:
>> + *      - hg_rawcommand errors
>> + *
>> + * */
>> +hg_cset_entry *hg_tip(hg_handle *handle, int(*callback)(const char *msg,
>> +                                               size_t len), char
>> *argument[]);
>> +
>>  /**
>>   * \brief The yield mechanism that will get the next entry.
>>   *
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel@selenic.com
>> http://selenic.com/mailman/listinfo/mercurial-devel
>>
>
>
Thanks for your replay :)
Idan Kamara - Sept. 15, 2013, 8:23 a.m.
On Sat, Sep 14, 2013 at 3:34 PM, Iulian Stana <julian.stana@gmail.com>wrote:

>
>  + *
>>> + * \param handle The handle of the connection, wherewith I want to
>>> communicate
>>> + * \param callback A function that will handle error data.
>>> + *                 A NULL pointer will ignore error data.
>>>
>>
>> What meaningful thing can a user do in this callback?
>>
>>
>
> What ever he wants to do with error data, print it do the stderr, store in
> some place
> or I don't know parse this data in his own way is his decision.
>

Parsing error data is a bit of a problem in Mercurial, since its output
isn't guaranteed to be stable between releases.
But more importantly, I don't think there's anything meaningful to do when
'hg tip' fails..

You already have errno to check for command errors, does it also expose a
generic 'command failed' error code?
If so, you could use that and store the error string somewhere, and have
strerror (or similar), return it.



>
>
>
>>  + * \param argument The option list. Will contain all option that you
>>> wish.
>>>
>>
>> If you let the user pass in more arguments, it has the potential of:
>>
>> 1) breaking your changeset parser (user passed --template)
>> 2) leaving unparsed data after you successfully parsed the changeset (not
>> sure how you deal with that)
>>
>>
> The last --template will overwrite all preview templates probably I must
> tell in
> documentation that is not allowed to use other template...
>

> hg tip --template '{rev}' --template '{node}' --template 'Template - {rev}
> - {node}\n'
>
> I'm not sure you really want that.
>>
>
> I really don't want to leave unparse data.
>

Right, so I'm not sure if you agree there's an issue here..

My comment was directed at making you question whether you really want to
allow
the user to pass arbitrary arguments to this function (and every other 'top
level' function
such as this).


>
>
>>
>>
>>> + * \retval cset The command return succesful, with a parse data.
>>>
>>
>> hg tip always returns a single changeset, wouldn't it be nicer if you
>> received a pointer
>> to hg_cset_entry and wrote the result there, rather than allocating one
>> inside?
>>
>
> Probably, I don't know:) I thought that it would be nice to return a
> cset_entry and
> to give user less work to do :) But this thing can be easy changed.
>

The current approach strikes me as more work for the user, because then
he's forced
to free() the malloc'ed cset. Where as if you let him pass a pointer, he
could
either pass a malloc'ed cset, or one off the stack, but the choice is his.
Giovanni Gherdovich - Sept. 15, 2013, 8:45 a.m.
Hello Idan and Iulian,

2013/9/15 Idan Kamara <idankk86@gmail.com>:
> On Sat, Sep 14, 2013 at 3:34 PM, Iulian Stana <julian.stana@gmail.com>
> wrote:
>>
>>
>>>> + *
>>>> + * \param handle The handle of the connection, wherewith I want to
>>>> communicate
>>>> + * \param callback A function that will handle error data.
>>>> + *                 A NULL pointer will ignore error data.
>>>
>>>
>>> What meaningful thing can a user do in this callback?
>>>
>>
>>
>> What ever he wants to do with error data, print it do the stderr, store in
>> some place
>> or I don't know parse this data in his own way is his decision.
>
>
> Parsing error data is a bit of a problem in Mercurial, since its output
> isn't guaranteed to be stable between releases.
> But more importantly, I don't think there's anything meaningful to do when
> 'hg tip' fails..
>
> You already have errno to check for command errors, does it also expose a
> generic 'command failed' error code?
> If so, you could use that and store the error string somewhere, and have
> strerror (or similar), return it.

They idea behind a callback to handle error messages is to let the user
decide if (1) print the err msg somewhere, like dialogue box or stderr or
(2) ignore.
Below I paste the IRC transcripts of the discussion we had with Matt
at the time.


>>>> + * \param argument The option list. Will contain all option that you
>>>> wish.
>>>
>>>
>>> If you let the user pass in more arguments, it has the potential of:
>>>
>>> 1) breaking your changeset parser (user passed --template)
>>> 2) leaving unparsed data after you successfully parsed the changeset (not
>>> sure how you deal with that)
>>>
>>
>> The last --template will overwrite all preview templates probably I must
>> tell in
>> documentation that is not allowed to use other template...
>>
>>
>> hg tip --template '{rev}' --template '{node}' --template 'Template - {rev}
>> - {node}\n'
>>
>>> I'm not sure you really want that.
>>
>>
>> I really don't want to leave unparse data.
>
>
> Right, so I'm not sure if you agree there's an issue here..

I agree that there is an issue here.
We don't just proxy commands trasparently to commandserver,
we inject a template that must be respected.

What does python-hglib and JavaHG do about that?

>
> My comment was directed at making you question whether you really want to
> allow
> the user to pass arbitrary arguments to this function (and every other 'top
> level' function
> such as this).

maybe "arbitrary options but not --template"...
I didn't think much of the implication of this.
What you say Iulian?

>>>> + * \retval cset The command return succesful, with a parse data.
>>>
>>>
>>> hg tip always returns a single changeset, wouldn't it be nicer if you
>>> received a pointer
>>> to hg_cset_entry and wrote the result there, rather than allocating one
>>> inside?
>>
>>
>> Probably, I don't know:) I thought that it would be nice to return a
>> cset_entry and
>> to give user less work to do :) But this thing can be easy changed.
>
>
> The current approach strikes me as more work for the user, because then he's
> forced
> to free() the malloc'ed cset. Where as if you let him pass a pointer, he
> could
> either pass a malloc'ed cset, or one off the stack, but the choice is his.

I second Idan here.
I don't know how common in the C world this is, but I personally find
disturbing when I have to free() things that I didn't malloc()ed myself.
It looks to me that the door is wide open to memory leaks because I
can forget something.

Cheers,
GGhh


-- -- >8 -- -- cut here -- -- >8 -- -- >8 -- -- cut here -- -- >8 -- -- >8
10:13 PM <mpm> What's your strategy for handling error messages?
10:15 PM <iulians> I save the output/error/debug data in some
hg_handle structure pointers.
         If the user what to see this data he can get it)
10:25 PM <mpm> The Python hglib typically uses callbacks for errors,
         which I think is probably a good fit for C.
10:27 PM <mpm> It lets the user say "I want to buffer my errors myself" or
         "I just want to set an error flag" or "I don't care about
anything but the exit code".
10:38 PM <iulians> mpm, How could this callback look? You enumerate 3
possibilities,
         les't say that the last one will pass to nowhere the data...
10:39 PM <mpm> Let's imagine the callback prototype looks like:
10:40 PM <mpm> int callback(const char *msg, size_t len);
10:40 PM <mpm> If the user wants to ignore the error message,
         she simply provides a function that returns right away.
10:41 PM <mpm> The library can even provide a pre-written version of
         this callback for convenience.
10:41 PM <mpm> Or treat a NULL callback pointer as 'ignore'.
10:43 PM <mpm> (Another more Pythonesque policy would be to treat a
NULL callback as 'fail',
         but C is used to ignoring things.)
10:44 PM <iulians> ok, let's say that NULL will be treat like 'ignore data'
10:48 PM <iulians> But how the callback function will look-like?
         What data will be pass to msg pointer?
10:52 PM <ggherdov> iulians: well, the message you get as output from
the cmd server I guess,
         carefully cooked in a single contiguous char*
10:53 PM <ggherdov> (since it might come over several 'e' writes,
         but you're polite and massage it a bit before passing to the fun ptr )
10:56 PM — ggherdov but actually the user would like to get
         that *msg content back at some point... uhm...
10:59 PM <ggherdov> ah no ! The user doesn't need it back !
         she just want a side effect to happen, based on that *msg...
         like printing it on screen or something
11:01 PM <ggherdov> iulians, does this make sense ?
11:03 PM <iulians> Not quite....
11:03 PM <ggherdov> What I mean is: do you have any operation that
         desperately need the content of *msg ?
         well, you put that operation inside the callback.
11:04 PM <mpm> "carefully cooked" <- No, don't cook it at all.
         When you get an 'e' packet, hand it off to the callback.
         Then go about your regular business.
11:05 PM <mpm> If an error message is split across multiple packets,
not hglib's problem.
11:05 PM <ggherdov> iulians: your only rule: *msg cannot go out of the
scope of the callback
         (said function only returns a int, status code).
         "Something" need *msg ? "something" goes into the callback
11:06 PM <ggherdov> ah mpm ok. iulians, take note !
11:06 PM <iulians> So everything that will be read from cmdserver
         will be pass immediately to the callback function
11:06 PM <ggherdov> iulians: error messages
11:07 PM <ggherdov> not "everything". your 'o' content needs to be
         parsed into structured data to allow programmatic manipulation
11:07 PM <mpm> Thing is, clients are probably not AIs so they'll
probably only do things
         like "print message immediately on stderr" or "show in a dialog box"
-- -- >8 -- -- cut here -- -- >8 -- -- >8 -- -- cut here -- -- >8 -- -- >8
Martin Geisler - Sept. 15, 2013, 10:25 a.m.
Giovanni Gherdovich <g.gherdovich@gmail.com> writes:

> Hello Idan and Iulian,
>
> 2013/9/15 Idan Kamara <idankk86@gmail.com>:
>>
>> My comment was directed at making you question whether you really
>> want to allow the user to pass arbitrary arguments to this function
>> (and every other 'top level' function such as this).
>
> maybe "arbitrary options but not --template"...

In JavaHG we tried to create a type-safe interface to the commands.
Basically you call methods corresponding to each command line flag we
support. Each method sets the flag and returns "this" so you can chain
the calls. For c-hglib you could perhaps pass a struct to the command,
something like this where the default_log_command_flags function creates
a struct with the flags at default values:

  log_command_flags *flags = default_log_command_flags();
  flags->copies = TRUE;
  flags->user = "me";
  flags->branch = "stable";

You then pass the struct to the log command together with any positional
arguments:

  log_command_result *result = hg_log(cmd_server, flags, "README")

and iterate over the results in the way already agreed on.

In JavaHg this is implemented with the LogCommand class which is a
subclass of a LogCommandFlags class:

  https://bitbucket.org/aragost/javahg/src/tip/src/main/java/com/aragost/javahg/commands/LogCommand.java
  https://bitbucket.org/aragost/javahg/src/tip/src/main/java/com/aragost/javahg/commands/flags/LogCommandFlags.java

That class is auto-generated from 'hg help log'. We filter the flags
based on a blacklist of known flags that we don't want to support, such
as --template, --print0, --git, --dry-run. The idea is that the library
takes care of supplying a suitable template and adding --git since we
rely on the output format when parsing the output.
Idan Kamara - Sept. 17, 2013, 7:59 a.m.
On Sun, Sep 15, 2013 at 11:45 AM, Giovanni Gherdovich <
g.gherdovich@gmail.com> wrote:

> Hello Idan and Iulian,
>
> 2013/9/15 Idan Kamara <idankk86@gmail.com>:
> > On Sat, Sep 14, 2013 at 3:34 PM, Iulian Stana <julian.stana@gmail.com>
> > wrote:
> >>
> >>
> >>>> + *
> >>>> + * \param handle The handle of the connection, wherewith I want to
> >>>> communicate
> >>>> + * \param callback A function that will handle error data.
> >>>> + *                 A NULL pointer will ignore error data.
> >>>
> >>>
> >>> What meaningful thing can a user do in this callback?
> >>>
> >>
> >>
> >> What ever he wants to do with error data, print it do the stderr, store
> in
> >> some place
> >> or I don't know parse this data in his own way is his decision.
> >
> >
> > Parsing error data is a bit of a problem in Mercurial, since its output
> > isn't guaranteed to be stable between releases.
> > But more importantly, I don't think there's anything meaningful to do
> when
> > 'hg tip' fails..
> >
> > You already have errno to check for command errors, does it also expose a
> > generic 'command failed' error code?
> > If so, you could use that and store the error string somewhere, and have
> > strerror (or similar), return it.
>
> They idea behind a callback to handle error messages is to let the user
> decide if (1) print the err msg somewhere, like dialogue box or stderr or
> (2) ignore.
> Below I paste the IRC transcripts of the discussion we had with Matt
> at the time.
>
>
> >>>> + * \param argument The option list. Will contain all option that you
> >>>> wish.
> >>>
> >>>
> >>> If you let the user pass in more arguments, it has the potential of:
> >>>
> >>> 1) breaking your changeset parser (user passed --template)
> >>> 2) leaving unparsed data after you successfully parsed the changeset
> (not
> >>> sure how you deal with that)
> >>>
> >>
> >> The last --template will overwrite all preview templates probably I must
> >> tell in
> >> documentation that is not allowed to use other template...
> >>
> >>
> >> hg tip --template '{rev}' --template '{node}' --template 'Template -
> {rev}
> >> - {node}\n'
> >>
> >>> I'm not sure you really want that.
> >>
> >>
> >> I really don't want to leave unparse data.
> >
> >
> > Right, so I'm not sure if you agree there's an issue here..
>
> I agree that there is an issue here.
> We don't just proxy commands trasparently to commandserver,
> we inject a template that must be respected.
>
> What does python-hglib and JavaHG do about that?


The high level interface doesn't let you pass arbitrary flags, it is
'typed', so you
can only pass what each command expects (excluding --template/style or other
flags that might alter the output in an unexpected way).
Iulian Stana - Sept. 17, 2013, 9:25 a.m.
2013/9/17 Idan Kamara <idankk86@gmail.com>

> On Sun, Sep 15, 2013 at 11:45 AM, Giovanni Gherdovich <
> g.gherdovich@gmail.com> wrote:
>
>> Hello Idan and Iulian,
>>
>> 2013/9/15 Idan Kamara <idankk86@gmail.com>:
>> > On Sat, Sep 14, 2013 at 3:34 PM, Iulian Stana <julian.stana@gmail.com>
>> > wrote:
>> >>
>> >>
>> >>>> + *
>> >>>> + * \param handle The handle of the connection, wherewith I want to
>> >>>> communicate
>> >>>> + * \param callback A function that will handle error data.
>> >>>> + *                 A NULL pointer will ignore error data.
>> >>>
>> >>>
>> >>> What meaningful thing can a user do in this callback?
>> >>>
>> >>
>> >>
>> >> What ever he wants to do with error data, print it do the stderr,
>> store in
>> >> some place
>> >> or I don't know parse this data in his own way is his decision.
>> >
>> >
>> > Parsing error data is a bit of a problem in Mercurial, since its output
>> > isn't guaranteed to be stable between releases.
>> > But more importantly, I don't think there's anything meaningful to do
>> when
>> > 'hg tip' fails..
>> >
>> > You already have errno to check for command errors, does it also expose
>> a
>> > generic 'command failed' error code?
>> > If so, you could use that and store the error string somewhere, and have
>> > strerror (or similar), return it.
>>
>> They idea behind a callback to handle error messages is to let the user
>> decide if (1) print the err msg somewhere, like dialogue box or stderr or
>> (2) ignore.
>> Below I paste the IRC transcripts of the discussion we had with Matt
>> at the time.
>>
>>
>> >>>> + * \param argument The option list. Will contain all option that you
>> >>>> wish.
>> >>>
>> >>>
>> >>> If you let the user pass in more arguments, it has the potential of:
>> >>>
>> >>> 1) breaking your changeset parser (user passed --template)
>> >>> 2) leaving unparsed data after you successfully parsed the changeset
>> (not
>> >>> sure how you deal with that)
>> >>>
>> >>
>> >> The last --template will overwrite all preview templates probably I
>> must
>> >> tell in
>> >> documentation that is not allowed to use other template...
>> >>
>> >>
>> >> hg tip --template '{rev}' --template '{node}' --template 'Template -
>> {rev}
>> >> - {node}\n'
>> >>
>> >>> I'm not sure you really want that.
>> >>
>> >>
>> >> I really don't want to leave unparse data.
>> >
>> >
>> > Right, so I'm not sure if you agree there's an issue here..
>>
>> I agree that there is an issue here.
>> We don't just proxy commands trasparently to commandserver,
>> we inject a template that must be respected.
>>
>> What does python-hglib and JavaHG do about that?
>
>
> The high level interface doesn't let you pass arbitrary flags, it is
> 'typed', so you
> can only pass what each command expects (excluding --template/style or
> other
> flags that might alter the output in an unexpected way).
>

Hi, Idan,

My high level commands signature can be found in the following forms:

1) hg_cset_entry *hg_tip(hg_handle *handle, int(*callback)(const char
*msg, size_t
len), char *argument[]);

2) int hg_pull(hg_handle *handle, int(*callback)(const char *msg, size_t
len), char *argument[]);

3) hg_csetstream_buffer *hg_log(hg_handle *handle, int(*callback)(const
char *msg, size_t len), char *argument[]);

For the first case I think that it will be better to pass the hg_cset_entry
structure
by a function argument, like you proposed, this means that those function
will be
more like second form, will return the exitcode received from cmd-server.

In the third form the function will return a yield-like mechanism, in this
case I am
allocate the space, but I also free this space if you use the the
hg_fetch_entry()
functions that I made available for users.

Probably you already see the pattern of those functions:

The first argument is the handle of the connection.

The second argument is a callback function that will handle the error data
received from cmd-server. My first thought was to store this data in a
pointer
and to let user to decide when he needs this data. Matt suggest that it
would
be better to use this callback function, in this way I don't need anymore to
store the error data. I just pass the received error data to this function.

The third argument is a list of arguments (a null terminate list that will
store
all options and all flags that users need). Why I choose this option? That
time when I started to think about possibilities of passing the flags I
found
three options:
1) to lay the options in the signature, like you did in the python-hglib,
but in C you cannot call a function just with the needed argument,
so you must pass a value for each agument,
2) to pass a list with wished options, like I already did
3) to create a flag structure for each command like Martin suggest
in his mail....

After some discussion we decided to use the second option, because
it's easier to implement, and will make the code more clear, I agree
with you that its not safe to let user pass what option he want, but in
this way, some features flags can be used more easier...

I think that Martin option will be the best in my case, if you have other
suggestion for how to implement this issue please tell me, in the meantime
I will start to prepare the ground for this change.

Patch

diff --git a/client.c b/client.c
--- a/client.c
+++ b/client.c
@@ -1393,6 +1393,28 @@ 
 	return lbuf;
 }
 
+/* The high level tip command for hglib API. */
+hg_cset_entry *hg_tip(hg_handle *handle, int(*callback)(const char *msg, 
+						size_t len), char *argument[])
+{
+	int exitcode;
+	char **command = cmdbuilder("tip", argument , "--template", CHANGESET,
+							NULL);
+
+	if(hg_rawcommand(handle, command) < 0){
+		return NULL;
+	}
+	free(command);
+	exitcode = hg_runcommand(handle, callback, NULL);
+	if(exitcode != 0)
+		return NULL;
+
+	hg_cset_entry *tip = malloc(sizeof(hg_cset_entry));
+	parse_changeset(handle->out_data + 1, tip);
+
+	return tip;
+}
+
 /* The yield next step. Getting the next entry. */
 int hg_fetch_entry(hg_stream_buffer *stream, int (*detect_byte)(char *buff, 
 			int buf_size, int data_on_pipe), int func_type)
diff --git a/client.h b/client.h
--- a/client.h
+++ b/client.h
@@ -2173,7 +2173,38 @@ 
 hg_linestream_buffer *hg_tags(hg_handle *handle, int(*callback)
 			(const char *msg, size_t len));
 
-	
+/**
+ * \brief hg_tip command for hglib API.
+ * 
+ * The tip revision (usually just called the tip) is the changeset most recently
+ * added to the repository (and therefore the most recently changed head).
+ *
+ * If you have just made a commit, that commit will be the tip. If you have just
+ * pulled changes from another repository, the tip of that repository becomes
+ * the current tip. The "tip" tag is special and cannot be renamed or assigned
+ * to a different changeset.
+ *
+ * Options/Argument list option:
+ *
+ *	-p, --patch	show patch
+ *	-g, --git		use git extended diff format
+ *	--style		display using template map file
+ *	--template		display with template
+ *
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \param callback A function that will handle error data. 
+ *                 A NULL pointer will ignore error data.
+ * \param argument The option list. Will contain all option that you wish.
+ * \retval cset The command return succesful, with a parse data.
+ * \retval NULL  The command failed. 
+ *
+ * errno can be:
+ *      - hg_rawcommand errors
+ *
+ * */
+hg_cset_entry *hg_tip(hg_handle *handle, int(*callback)(const char *msg, 
+						size_t len), char *argument[]);
+
 /**
  * \brief The yield mechanism that will get the next entry.
  *