Patchwork [3,of,3,RFC,-V2] model (2): c-hglib: hg_add() level 1 function

login
register
mail settings
Submitter Iulian Stana
Date Aug. 20, 2013, 2:36 p.m.
Message ID <1c9ebf510ae33f30c168.1377009404@doppler>
Download mbox | patch
Permalink /patch/2232/
State Deferred
Headers show

Comments

Iulian Stana - Aug. 20, 2013, 2:36 p.m.
# HG changeset patch
# User Iulian Stana <julian.stana@gmail.com>
# Date 1377008557 -10800
#      Tue Aug 20 17:22:37 2013 +0300
# Node ID 1c9ebf510ae33f30c168c96a4dc5c9d38ef9c08d
# Parent  4cd3ea6bec95f12f70ee1bb51b7cc2cf66788408
model (2): c-hglib: hg_add() level 1 function

This mechanism could be called model (2):

(2) Wait for the commandserv to complete *all* his actions in response to
    the issued command, which is cache the commandserv response somewhere,
    and return the actual exitcode (channel 'r' from commandserv)
    as the result of the chglib API call"


The add command and more other mercurial commands, are not performing any kind
of parse data. The most important thing on those commands is the exitcode, if
everything works well or not.

More than that those commands will have a quickly exit. There is needed a short
time to process them.

But sometimes the command server could send some error or debug data, that
probably the user would like to know about, or to process it. For this thing I
created three pointers where the data will be stored. (This data is unparse!)

Patch

diff --git a/client.c b/client.c
--- a/client.c
+++ b/client.c
@@ -11,7 +11,6 @@ 
 
 
 #include "client.h"
-#include "utils.h"
 
 #define HGPATH "hg"
 #define CHANGESET "{rev}\\0{node}\\0{tags}\\0{branch}\\0{author}\\0{desc}\
@@ -89,6 +88,78 @@ 
 	return 0;
 }
 
+/* Adding to the destination pointer the source pointer. */
+int adding_data(char **dest, char *source)
+{
+	if(*dest == NULL){
+		*dest = malloc(strlen(source) + 1);
+		memcpy(*dest, source, strlen(source) + 1);
+	} else {
+		*dest = realloc(*dest, strlen(*dest) + strlen(source) + 1);
+		memcpy(*dest + strlen(*dest), source, strlen(source) + 1);
+	}
+	return 0;
+}
+
+/* return the output data. */
+char *get_output_data(hg_handle *handle)
+{
+	return handle->out_data;
+}
+
+/* return the error data. */
+char *get_error_data(hg_handle *handle)
+{
+	return handle->error_data;
+}
+
+/* return the debug data. */
+char *get_debug_data(hg_handle *handle)
+{
+	return handle->debug_data;
+}
+
+/* Read and add to some pointers the data */
+int runcommand(hg_handle *handle)
+{
+	char buff[4096];
+	int exitcode;
+	int ns;
+
+	while(hg_channel(handle) != 'r'){
+		while(ns = hg_rawread(handle, buff, 4096), ns > 0){
+			if(hg_channel(handle) == 'o'){
+				adding_data(&handle->out_data, buff);
+			}
+			else if(hg_channel(handle) == 'e'){
+				adding_data(&handle->error_data, buff);
+			}
+			else{
+				adding_data(&handle->debug_data, buff);
+			}
+		}
+	}
+	exitcode = hg_exitcode(handle);
+
+	return exitcode;
+}
+
+/* The high level add command for hglib API.*/
+int hg_add(hg_handle *handle, char *argument[])
+{
+	int exitcode;
+	char **command = cmdbuilder("add", argument, NULL);
+
+	if(hg_rawcommand(handle, command) < 0){
+		return -1;
+	}
+	free(command);
+
+	exitcode = runcommand(handle);
+
+	return exitcode;
+}
+
 /* The high level log command for hglib API. */
 hg_log_iterator *hg_log(hg_handle *handle, char *option[])
 {
diff --git a/client.h b/client.h
--- a/client.h
+++ b/client.h
@@ -213,6 +213,50 @@ 
 int hg_exitcode(hg_handle *handle);
 
 /**
+ * \brief Getting the output data, received from the last command.
+ *
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \retval string Indicate the output data.
+ **/
+char *get_output_data(hg_handle *handle);
+
+/**
+ * \brief Getting the error data, received from the last command.
+ *
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \retval string Indicate the error data.
+ **/
+char *get_error_data(hg_handle *handle);
+
+/**
+ * \brief Getting the debug data, received from the last command.
+ *
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \retval string Indicate the debug data.
+ **/
+char *get_debug_data(hg_handle *handle);
+
+/**
+ * \brief hg_add command for hglib API.
+ *
+ * Add the specified files on the next commit.
+ * If no files are given, add all files to the repository.
+ *
+ *      dryrun - do no perform actions
+ *      subrepos - recurse into subrepositories
+ *      include - include names matching the given patterns
+ *      exclude - exclude names matching the given patterns
+ *
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \param option The option list for mercurial add command.
+ * \retval exitcode  To indicate the end of add_command.
+ *
+ * errno can be:
+ *      - hg_rawcommand errors
+ * */
+int hg_add(hg_handle *handle, char *argument[]);
+
+/**
  * \brief hg_log command for hglib API.
  *
  * It's an advance function to get revision history. It's more like the start 
diff --git a/main.c b/main.c
--- a/main.c
+++ b/main.c
@@ -89,6 +89,7 @@ 
 {
 	printf("Select test case to run:\n");
 	printf("1) log \n");
+	printf("2) add \n");
 	printf("\n");
 	printf("Your choice: ");
 }
@@ -105,7 +106,7 @@ 
 
 	print_select_case();
 	scanf("%d", &select_case);
-	if(select_case < 1 || select_case > 1){
+	if(select_case < 1 || select_case > 2){
 		printf("Your choice is not an option...\n");
 		return -1;
 	}
@@ -121,6 +122,23 @@ 
 			hg_close(&handle);
 			clean_tmp();
 			break;
+		case 2:
+			setup_tmp();
+			
+			system("touch 'foo_bar'");
+			system("hg st");
+
+			handle = hg_open(NULL, "");
+			char *arguments[] = {"foo_barr","--ff", NULL};
+			printf("exitcode %d\n", hg_add(handle, arguments));
+			printf("out_data = %s \n", get_output_data(handle));
+			printf("debug_data = %s \n", get_debug_data(handle));
+			
+			system("hg st");
+			
+			hg_close(&handle);
+			clean_tmp();
+			break;
 		default:
 			break;
 	}