Patchwork [3,of,5,V2] chg: implement validate in hgclient

login
register
mail settings
Submitter Jun Wu
Date March 4, 2016, 1:28 p.m.
Message ID <314e2f98e29e590d2bae.1457098136@x1c>
Download mbox | patch
Permalink /patch/13591/
State Superseded
Commit a5c773acb01877c12b19a27f508251b334e562d0
Delegated to: Yuya Nishihara
Headers show

Comments

Jun Wu - March 4, 2016, 1:28 p.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1457090189 0
#      Fri Mar 04 11:16:29 2016 +0000
# Node ID 314e2f98e29e590d2bae1d3604f54478ce47cbc6
# Parent  099b8303cd3dcfa7d4446bf31f07f4f0975bda08
chg: implement validate in hgclient

This patch implements the corresponding validate command just added to the
server, and a helper method to parse the list of '\0' terminated strings
returned by the server in hgclient.

Patch

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,65 @@ 
 }
 
 /*!
+ * Send command line arguments to let the server load the repo config and check
+ * whether it can process our request directly or not.
+ * Make sure hgc_setenv is called before calling this.
+ *
+ * @return - 0: the server believes it can handle our request, or does not
+ *           support "validate" command.
+ *         - n (> 0): the server cannot handle our request and it sent
+ *           instructions telling us how to find another server which is more
+ *           likely to be able to handle our request.
+ *           To get the instruction strings, call hgc_parselist with size = n,
+ *           and make sure it returns a number < n.
+ *           See chgserver.py for possible instructions.
+ */
+size_t hgc_validate(hgclient_t *hgc, const char *const args[], size_t argsize)
+{
+	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 can handle our request */
+	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');
+	return n;
+}
+
+/*!
+ * Parse a list of '\0' terminated strings from the server response.
+ *
+ * @param pbuf  pointer to a pre-allocated buffer
+ * @param size  the size of the buffer (bytes / sizeof(char*))
+ * @return number of (char *) written
+ */
+size_t hgc_parselist(hgclient_t *hgc, const char **pbuf, size_t size)
+{
+	size_t n = 0, i;
+	const char *start = NULL;
+	for (i = 0; i < hgc->ctx.datasize; ++i) {
+		if (hgc->ctx.data[i] == '\0') {
+			pbuf[n++] = start;
+			if (n >= size)
+				break;
+			start = NULL;
+		} else if (start == NULL) {
+			start = hgc->ctx.data + i;
+		}
+	}
+	return n;
+}
+
+/*!
  * Execute the specified Mercurial command
  *
  * @return result code
diff --git a/contrib/chg/hgclient.h b/contrib/chg/hgclient.h
--- a/contrib/chg/hgclient.h
+++ b/contrib/chg/hgclient.h
@@ -24,6 +24,8 @@ 
 void hgc_attachio(hgclient_t *hgc);
 const char *hgc_getpager(hgclient_t *hgc, const char *const args[],
 			 size_t argsize);
+size_t hgc_parselist(hgclient_t *hgc, const char **pbuf, size_t size);
 void hgc_setenv(hgclient_t *hgc, const char *const envp[]);
+size_t hgc_validate(hgclient_t *hgc, const char *const args[], size_t argsize);
 
 #endif  /* HGCLIENT_H_ */