[PATCH 08 of 10] chg: implement validate in hgclient
Yuya Nishihara
yuya at tcha.org
Thu Mar 3 11:07:50 EST 2016
On Wed, 2 Mar 2016 10:44:10 +0000, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu <quark at fb.com>
> # Date 1456913788 0
> # Wed Mar 02 10:16:28 2016 +0000
> # Node ID 801df1c31d0c49a19fe3dca0025b393dcc292599
> # Parent 7a0eaf66c464e1fcab9b8470811de0d88ef754ff
> chg: implement validate in hgclient
>
> This patch implements the corresponding validate method in hgclient.
> It will return action strings as is but will not take any real action.
>
> diff --git a/contrib/chg/hgclient.c b/contrib/chg/hgclient.c
> --- a/contrib/chg/hgclient.c
> +++ b/contrib/chg/hgclient.c
> @@ -34,6 +34,7 @@
> CAP_GETPAGER = 0x0400,
> CAP_SETENV = 0x0800,
> CAP_SETUMASK = 0x1000,
> + CAP_VALIDATE = 0x2000,
> };
>
> typedef struct {
> @@ -49,6 +50,7 @@
> {"getpager", CAP_GETPAGER},
> {"setenv", CAP_SETENV},
> {"setumask", CAP_SETUMASK},
> + {"validate", CAP_VALIDATE},
> {NULL, 0}, /* terminator */
> };
>
> @@ -463,6 +465,52 @@
> }
>
> /*!
> + * Send command line arguments to let the server decide whether it has the
> + * up-to-date config, extensions and can handle our request.
> + * @return - NULL, the server passed or does not support validation.
> + * - a list of strings, which are the instructions returned by the
> + * server, the list (not the strings) must be freed by the caller.
> + * the last string is guaranteed NULL.
> + */
> +const char **hgc_validate(hgclient_t *hgc, const char *const args[],
> + size_t argsize)
I'm not a fan of "must be freed by the caller" design. Since we know the
list is small, it could be a destination argument and return the actual length.
> +{
> + assert(hgc);
> + if (!(hgc->capflags & CAP_VALIDATE))
> + return NULL;
> +
> + packcmdargs(&hgc->ctx, args, argsize);
> + writeblockrequest(hgc, "validate");
> + readchannel(hgc);
> +
> + /* the server returns '\0' if it passed validation */
> + if (hgc->ctx.datasize <= 1)
> + return NULL;
> +
> + /* a list of '\0' terminated strings */
> + size_t n = 1, i;
> + for (i = 0; i < hgc->ctx.datasize; ++i)
> + n += (hgc->ctx.data[i] == '\0');
> +
> + n *= sizeof(char **);
> + const char **insts = (const char **)mallocx(n);
> + memset(insts, 0, n);
> +
> + int waszero = 1;
> + n = 0;
> + for (i = 0; i < hgc->ctx.datasize; ++i) {
> + if (hgc->ctx.data[i] == '\0') {
> + waszero = 1;
> + } else {
> + if (waszero)
> + insts[n++] = hgc->ctx.data + i;
> + waszero = 0;
> + }
> + }
It would overflow if the data isn't NULL-terminated.
memchr() might be useful.
More information about the Mercurial-devel
mailing list