[PATCH c-hglib] hg_rawcommand: send a command to the mercurial command

Iulian Stana julian.stana at gmail.com
Wed Sep 18 15:54:03 CDT 2013


# HG changeset patch
# User Iulian Stana <julian.stana at gmail.com>
# Date 1379452976 -10800
#      Wed Sep 18 00:22:56 2013 +0300
# Node ID 56adaa5609236d29884eab4c1a1799a2692d3306
# Parent  408d6488f726fc88bba3e64dfcc881f1651f3b91
hg_rawcommand: send a command to the mercurial command

The hg_rawcommand, it's the function that ask cmdserver for a particular
command. Using this function you can interogate the command server.

cmd_prepare is the function that will concatenate the hg_rawcommand argument
list, and will return a string that will contain the wished 'query'.

After you call hg_rawcommand function, the command server will start sending
data to the pipe. The command server will end his action with a 'r' channel
output data.

In this function the handle, protect field is set to 1, and will block the
possibility of calling the hg_rawcommand for a second time if you haven't called
exitcode function (ending the current flow of data).

diff --git a/hglib/client.c b/hglib/client.c
--- a/hglib/client.c
+++ b/hglib/client.c
@@ -199,3 +199,43 @@
 	return 0;
 }
 
+/*
+ * Sending a command to the mercurial command server, through the given handle.
+ * */
+int hg_rawcommand(hg_handle *handle, char *const command[])
+{
+	if (!handle) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (handle->protect) {
+		errno = EPERM;
+		return -1;
+	}
+
+	char runcommand[] = "runcommand\n";
+	int cmd_size = 0;
+	char *cmd_send = cmd_prepare(command, &cmd_size);
+	uint32_t big_endian_size = swap_uint32(cmd_size);
+
+	if (write(handle->p_write, runcommand, strlen(runcommand)) < 0) {
+		free(cmd_send);
+		return -1;
+	}
+	if (write(handle->p_write, &big_endian_size, sizeof(uint32_t)) < 0) {
+		free(cmd_send);
+		return -1;
+	}
+	if (write(handle->p_write, cmd_send, cmd_size) < 0) {
+		free(cmd_send);
+		return -1;
+	}
+
+	free_data(handle);
+	handle->protect = 1;
+	free(cmd_send);
+	return 0;
+}
+
+
diff --git a/hglib/utils.c b/hglib/utils.c
--- a/hglib/utils.c
+++ b/hglib/utils.c
@@ -15,3 +15,29 @@
 	return (val << 16) | (val >> 16);
 }
 
+/*
+ * Prepare the command for sending process.
+ * */
+char *cmd_prepare(char *const command[], int *cmd_size)
+{
+	size_t cmd_length = 0;
+	char *new_cmd;
+	int i = 0;
+
+	while (command[i]) {
+		cmd_length += strlen(command[i]) + 1;
+		++i;
+	}
+
+	new_cmd = malloc(cmd_length + 1);
+	i = 0;
+	while (command[i]) {
+		strcpy(new_cmd, command[i]);
+		new_cmd += strlen(command[i]) + 1;
+		++i;
+	}
+	new_cmd -= cmd_length;
+
+	*cmd_size = cmd_length - 1;
+	return new_cmd;
+}
diff --git a/hglib/utils.h b/hglib/utils.h
--- a/hglib/utils.h
+++ b/hglib/utils.h
@@ -10,4 +10,22 @@
  * */
 uint32_t swap_uint32(uint32_t val);
 
+/**
+ * \brief Prepare the command for sending process. 
+ * 
+ * Replace all the blank space with the '\0' character.
+ * \param command an array that will contain the mercurial command
+ * \param cmd_size - array size
+ * \retval string representing the command that will be send to cmdsrv
+ * \retval *cmd_size will be set on string size
+ * 
+ * \code
+ *    char *command[] = {"tip", "-p", NULL};
+ *    char *cmd_str = cmd_prepare(command, 0);
+ *    prinf("==%s==", cmd_str);
+ *    ---> ==tip\0-p==
+ * \endcode
+ * */
+char *cmd_prepare(char *const command[], int *cmd_size);
+
 #endif


More information about the Mercurial-devel mailing list