{"thread":{"id":"821","subject":"[PATCH] git-daemon server","startedAt":"2005-06-03T15:22:12Z","lastAt":"2005-06-05T23:17:56Z","messageCount":32,"participants":["Jason McMullan","Linus Torvalds","McMullan, Jason","Junio C Hamano","Daniel Barkalow","Daniel Serpell","Petr Baudis"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"4493","messageId":"20050603152212.GA4598@jmcmullan.timesys","threadId":"821","inReplyTo":null,"subject":"[PATCH] git-daemon server","fromName":"Jason McMullan","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-03T15:22:12Z","receivedAt":"2005-06-03T15:22:12Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"git-daemon - Client/server for exchanging GIT objects\n\nRequires: [PATCH] Expose more sha1_file.c interfaces\nRequires: [PATCH] Anal retentive 'const unsigned char *sha1'\nSigned-off-by: Jason McMullan <jason.mcmullan@timesys.com>\n\nGIT daemon is a symmetric protocol for exchanging objects\nbetween repositories. It has the following features:\n\n\t* Can use TCP, Unix domain sockets, or stdin/stdout\n\t* Verifies received SHA1 objects are valid and fully\n\t  connected before they are stored in the object database,\n\t  including delta objects.\n\t* Fully symmetric protocol\n\t* Only pulls the dependencies of the requested object -\n\t  allows you to place *multiple* projects in one GIT database.\n\t* Proper head locking, allows either lazy or cmp-xchg updates\n\t  (lazy is just 'head head-id old-sha1 new-sha1', cmp-xchg is\n           'send new-sha1; head head-id old-sha1 new-sha1' )\n\nTODO:\n-----\n\n\t* Command line 'send' of a SHA1 from the local database\n\t  (for the cmd-xchg mechanism. Lazy works out-of-the box)\n\t* Optional auto-deltification of transmitted objects\n\t* More documentation\n\t* Test cases for 'make test'\n\t* Merge verify-before-update logic into pull.c\n\nGIT Daemon Protocol Commands:\n-----------------------------\n\nversion::\n        Requests the version string, returned in an error message\n        Expects: 'error'\n\nhead <head-id>::\n        Requests SHA1 of the <head-id>\n        Expects: 'sha1' or 'error'\n\nhead <head-id> <old-sha1> <new-sha1>::\n        Requests that <head-id> be updated with <new-sha1>. Use\n        '--' for <old-sha1> to create a new head.\n        Expects: 'sha1', 'request', or 'error'\n\nexists <sha1>::\n        Determine if SHA1 exists in remote\n        Expects: 'sha1' or 'error'\n\nrequest <sha1>::\n        Request SHA1 object. \n        Expects: 'send' or 'error'\n\nsend <sha1>::\n        Send SHA1 object.\n        Expects: 'sha1' or 'error'\n\nerror <key> <hex-code> <error-message>::\n        Returned error code\n        Expects: Nothing\n\nsha1 <key> <hex-sha1>::\n        Success message for 'head' and 'send' commands.\n\n\ndiff -u b/daemon.c b/daemon.c\n--- b/daemon.c\n+++ b/daemon.c\n@@ -0,0 +1,827 @@\n+#include <stdio.h>\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <ctype.h>\n+#include <assert.h>\n+#include <signal.h>\n+#include <sys/un.h>\n+#include <sys/file.h>\n+#include <sys/types.h>\n+#include <sys/wait.h>\n+#include <sys/socket.h>\n+#include <netinet/in.h>\n+#include <netinet/ip.h>\n+#include <arpa/inet.h>\n+#include <netdb.h>\n+\n+#ifndef UNIX_PATH_MAX\n+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)NULL)->sun_path)\n+#endif\n+\n+#include \"cache.h\"\n+#include \"delta.h\"\n+#include \"object.h\"\n+#include \"blob.h\"\n+#include \"tree.h\"\n+#include \"commit.h\"\n+#include \"tag.h\"\n+\n+#define ERROR_VERSION\t\t\t0,\"GIT Daemon protocol version 0.0\"\n+#define ERROR_INVALID\t\t\t1,\"Invalid command\"\n+#define ERROR_REQUEST_INVALID\t\t100,\"SHA1 does not exist\"\n+#define ERROR_HEAD_BAD(hash)\t\t200,\"Head is not at hash %s\",hash\n+#define ERROR_HEAD_INVALID\t\t201,\"Head does not exist\"\n+#define ERROR_HEAD_LOCK\t\t\t202,\"Head can't be locked\"\n+#define ERROR_HEAD_UPDATE\t\t203,\"Head can't be updated\"\n+#define ERROR_HEAD_SHA1_INVALID(sha1)\t204,\"SHA1 %s does not exist\",sha1\n+#define ERROR_SEND_INVALID\t\t300,\"Invalid data sent on send\"\n+\n+/* Protocol is symmetric, both client and server\n+ * use the same commands.\n+ *\n+ * version\\n -> error -- 0 <Version string>\\n\n+ *\n+ * head <head-id>\\n -> sha1 <head-id> <sha1>\\n\n+ *\n+ * head <head-id> <old-sha1> <new-sha1>\\n -> sha1 <head-id> <new-sha1>\\n\n+ *\n+ * request <sha1>\\n -> send <sha1> <hex-bytes>\\n<bytes...>\n+ *\n+ * send <sha1> <hex-bytes>\\n<bytes...> -> sha1 -- <sha1>\\n\n+ *\n+ * exists <sha1>\\n -> sha1 -- <sha1>\\n\n+ *\n+ * sha1 <any> <sha1>\\n -> no-op\n+ *\n+ * error <key> <hex-code> <error string>\\n -> no-op\n+ *\n+ */\n+\n+static int fd_in=0, fd_out=1;\n+\n+static int process_request();\n+static int send_request(const unsigned char *sha1);\n+static const char *git_dir;\n+\n+void *map_file(int fd, size_t size)\n+{\n+\tvoid *map;\n+\n+\tif (fd < 0) {\n+\t\terror(\"cannot map file on fd %d\", fd);\n+\t\treturn NULL;\n+\t}\n+\n+\tmap = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);\n+\tif (-1 == (int)(long)map)\n+\t\treturn NULL;\n+\treturn map;\n+}\n+\n+static int sha1_retrieve(const unsigned char *sha1)\n+{\n+\tint err;\n+\n+       \tif (!has_sha1_file(sha1)) {\n+\t\terr = send_request(sha1);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int verify_file(int fd, unsigned long mapsize, const unsigned char *sha1, char *type)\n+{\n+\tvoid *map, *buffer;\n+\tchar hdr[8192];\n+\tstruct object *obj;\n+\tunsigned long size;\n+\tz_stream stream;\n+\tint err;\n+\n+\tmap = map_file(fd, mapsize);\n+\tif (map) {\n+\t\terr = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));\n+\t\tif (err < Z_OK || parse_sha1_header(hdr, type, &size) < 0) {\n+\t\t\tmunmap(map, mapsize);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tbuffer = unpack_sha1_rest(&stream, hdr, size);\n+\t\tmunmap(map, size);\n+\n+\t\tif (buffer == NULL) {\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (buffer && !strcmp(type, \"delta\")) {\n+\t\t\tvoid *ref = NULL, *delta = buffer;\n+\t\t\tunsigned long ref_size, delta_size = size;\n+\t\t\tbuffer = NULL;\n+\t\t\tif (delta_size <= 20) {\n+\t\t\t\tfree(buffer);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\terr = sha1_retrieve(delta);\n+\t\t\tif (err < 0) {\n+\t\t\t\tfree(buffer);\n+\t\t\t\treturn err;\n+\t\t\t}\n+\t\t\tref = read_sha1_file(delta, type, &ref_size);\n+\n+\t\t\tif (ref == NULL) {\n+\t\t\t\tfree(buffer);\n+\t\t\t\treturn err;\n+\t\t\t}\n+\n+\t\t\tbuffer = patch_delta(ref, ref_size,\n+\t\t\t\t\t  delta+20, delta_size-20, \n+\t\t\t\t\t  &size);\n+\t\t\tfree(delta);\n+\t\t\tfree(ref);\n+\t\t}\n+\n+\t\tif (!strcmp(type, \"blob\")) {\n+\t\t\tstruct blob *blob = lookup_blob(sha1);\n+\t\t\tparse_blob_buffer(blob, buffer, size);\n+\t\t\tobj = &blob->object;\n+\t\t} else if (!strcmp(type, \"tree\")) {\n+\t\t\tstruct tree *tree = lookup_tree(sha1);\n+\t\t\tparse_tree_buffer(tree, buffer, size);\n+\t\t\tobj = &tree->object;\n+\t\t} else if (!strcmp(type, \"commit\")) {\n+\t\t\tstruct commit *commit = lookup_commit(sha1);\n+\t\t\tparse_commit_buffer(commit, buffer, size);\n+\t\t\tif (!commit->buffer) {\n+\t\t\t\tcommit->buffer = buffer;\n+\t\t\t\tbuffer = NULL;\n+\t\t\t}\n+\t\t\tobj = &commit->object;\n+\t\t} else if (!strcmp(type, \"tag\")) {\n+\t\t\tstruct tag *tag = lookup_tag(sha1);\n+\t\t\tparse_tag_buffer(tag, buffer, size);\n+\t\t\tobj = &tag->object;\n+\t\t} else {\n+\t\t\tobj = NULL;\n+\t\t}\n+\n+\t\tfree(buffer);\n+\n+\t\tif (obj) {\n+\t\t\tstruct object_list *refs;\n+\n+\t\t\tfor (refs = obj->refs; refs ; refs = refs->next) {\n+\t\t\t\terr = sha1_retrieve(refs->item->sha1);\n+\t\t\t\tif (err < 0)\n+\t\t\t\t\treturn err;\n+\t\t\t}\n+\t\t\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t}\n+\treturn -1;\n+}\n+\n+static int send_command(int argc, char **argv)\n+{\n+\tchar buff[1024];\n+\tint len, size;\n+\n+\tsize = snprintf(buff, sizeof(buff), \"%s\", argv[0]);\n+\tfor ( argc--,argv++; argc > 0 ; argc--, argv++) {\n+\t\tlen = snprintf(buff + size, sizeof(buff) - size, \" %s\", argv[0]);\n+\t\tsize += len;\n+\t}\n+\tbuff[size++]='\\n';\n+\treturn write(fd_out, buff, size);\n+}\n+\n+static int send_error(const char *key,int code,const char *errstr,...)\n+{\n+\tva_list args;\n+\tstatic char buff[1024];\n+\tint len;\n+\n+\tva_start(args, errstr);\n+\n+\tlen = snprintf(buff, sizeof(buff), \"error %s %x \", key ? key : \"--\", code);\n+\twrite(fd_out, buff, len);\n+\tlen = vsnprintf(buff, sizeof(buff), errstr, args);\n+\twrite(fd_out, buff, len);\n+\twrite(fd_out, \"\\n\", 1);\n+\n+\tva_end(args);\n+\n+\treturn 0;\n+}\n+\n+static int send_sha1(const char *key, const unsigned char *sha1)\n+{\n+\tchar buff[2048];\n+\tint len;\n+\n+\tlen = snprintf(buff,sizeof(buff), \"sha1 %s %s\\n\",key ? key : \"--\", sha1_to_hex(sha1));\n+\treturn write(fd_out, buff, len);\n+}\n+\n+static int send_send(const unsigned char *sha1, int size, void *data)\n+{\n+\tchar buff[2048];\n+\tint len, err;\n+\n+\tlen = snprintf(buff,sizeof(buff), \"send %s %x\\n\",sha1_to_hex(sha1),size);\n+\terr = write(fd_out, buff, len);\n+\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\terr = write(fd_out, data, size);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn process_request();\n+}\n+\n+static int send_request(const unsigned char *sha1)\n+{\n+\tchar buff[2048];\n+\tint len, err;\n+\n+\tlen = snprintf(buff,sizeof(buff), \"request %s\\n\",sha1_to_hex(sha1));\n+\terr = write(fd_out, buff, len);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\treturn process_request();\n+}\n+\n+\n+static inline int lock_file(const char *path, int is_create)\n+{\n+\tint fd;\n+\n+\tfd = open(path, O_RDONLY);\n+\tif (fd < 0 && is_create) {\n+\t\tfd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);\n+\t} else if (is_create) {\n+\t\tclose(fd);\n+\t\treturn -1;\n+\t}\n+\n+\tif (fd < 0)\n+\t\treturn -1;\n+\n+\tif (flock(fd, LOCK_EX | LOCK_NB) < 0) {\n+\t\tclose(fd);\n+\t\tif (is_create)\n+\t\t\tunlink(path);\n+\t\treturn -1;\n+\t}\n+\n+\treturn fd;\n+}\n+\n+static inline void unlock_file(int fd)\n+{\n+\tflock(fd, LOCK_UN);\n+\tclose(fd);\n+}\n+\n+static int cmd_version(int argc, char **argv)\n+{\n+\treturn send_error(\"--\",ERROR_VERSION);\n+}\n+\n+/* Return < 0 on I/O error\n+ */\n+static int cmd_head(int argc, char **argv)\n+{\n+\tint len, err;\n+\n+\tif (argc == 2) {\n+\t\tunsigned char sha1[20];\n+\n+\t\t/* Get SHA1 for head */\n+\t       \terr = get_sha1(argv[1], sha1);\n+\t\tif (err < 0)\n+\t\t\treturn send_error(argv[1],ERROR_HEAD_INVALID);\n+\n+\t\treturn send_sha1(argv[1],sha1);\n+\t} else if (argc == 4) {\n+\t\tchar head_sha1[20], sha1[20], sha1_new[20];\n+\t\tint fd, head_fd;\n+\t\tstatic char buff[256];\n+\t\tstatic char hfile[PATH_MAX];\n+\t\tstatic char hfile_new[PATH_MAX];\n+\t\tint is_create;\n+\t\tconst char *head=argv[1], *old_hash=argv[2], *new_hash=argv[3];\n+\n+\t\tis_create = (strcmp(old_hash,\"--\")==0);\n+\n+\t\t/* Is the head name valid? */\n+\t\tif (strchr(head,'/') != NULL)\n+\t\t\treturn send_error(head,ERROR_HEAD_INVALID);\n+\n+\t\t/* lock head */\n+\t\tlen = snprintf(hfile, sizeof(hfile), \"%s/refs/heads/%s\", git_dir, argv[1]);\n+\t\tstrcpy(hfile_new, hfile);\n+\t\tstrcpy(hfile_new + len, \".new\");\n+\t\thead_fd = lock_file(hfile, is_create);\n+\t\tif (head_fd < 0) {\n+\t\t\treturn send_error(head,ERROR_HEAD_LOCK);\n+\t\t}\n+\n+\t\t/* Verify that we know what we're doing\n+\t\t * to do a cmp-xchg update\n+\t\t */\n+\t\tif (!is_create) {\n+\t       \t\terr = get_sha1(head, head_sha1);\n+\t\t\tif (err < 0) {\n+\t\t\t\tif (is_create) unlink(hfile);\n+\t\t\t\tunlock_file(head_fd);\n+\t\t\t\treturn send_error(head, ERROR_HEAD_INVALID);\n+\t\t\t}\n+\n+\t\t\terr = get_sha1(old_hash, sha1);\n+\t\t\tif (err < 0) {\n+\t\t\t\tif (is_create) unlink(hfile);\n+\t\t\t\tunlock_file(head_fd);\n+\t\t\t\treturn send_error(head, ERROR_HEAD_SHA1_INVALID(old_hash));\n+\t\t\t}\n+\n+\t\t\tif (memcmp(head_sha1, sha1, 20) != 0) {\n+\t\t\t\tif (is_create) unlink(hfile);\n+\t\t\t\tunlock_file(head_fd);\n+\t\t\t\treturn send_error(head, ERROR_HEAD_BAD(old_hash));\n+\t\t\t}\n+\t\t}\n+\n+\n+\t\t/* Is the new head id even a valid string? */\n+\t\terr = get_sha1(new_hash, sha1_new);\n+\t\tif (err < 0) {\n+\t\t\tif (is_create) unlink(hfile);\n+\t\t\tunlock_file(head_fd);\n+\t\t\treturn send_error(head,ERROR_HEAD_SHA1_INVALID(new_hash));\n+\t\t}\n+\n+\t\t/* If new-sha1 == old-sha1, short circuit to end */\n+\t\tif (memcmp(sha1_new, sha1, 20) == 0)\n+\t\t\tgoto done;\n+\n+\t\t/* Verify that new-sha1 is in the database */\n+\t\terr = sha1_retrieve(sha1_new);\n+\t\tif (err < 0) {\n+\t\t\tif (is_create) unlink(hfile);\n+\t\t\tunlock_file(head_fd);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\t/* We now have the SHA1. Update head */\n+\t\tfd = open(hfile_new, O_RDWR | O_CREAT | O_TRUNC, 0644);\n+\t\tif (fd < 0) {\n+\t\t\tif (is_create) unlink(hfile);\n+\t\t\tunlock_file(head_fd);\n+\t\t\treturn send_error(argv[1],ERROR_HEAD_UPDATE);\n+\t\t}\n+\n+\t\tlen = snprintf(buff, sizeof(buff), \"%s\\n\", sha1_to_hex(sha1_new));\n+\t\terr = write(fd, buff, len);\n+\t\tclose(fd);\n+\t\tif (err != len) {\n+\t\t\tif (is_create) unlink(hfile);\n+\t\t\tunlink(hfile_new);\n+\t\t\tunlock_file(head_fd);\n+\t\t\treturn send_error(argv[1],ERROR_HEAD_UPDATE);\n+\t\t}\n+\n+\t\terr = rename(hfile_new, hfile);\n+\t\tif (err < 0) {\n+\t\t\tif (is_create) unlink(hfile);\n+\t\t\tunlock_file(head_fd);\n+\t\t\treturn send_error(argv[1],ERROR_HEAD_UPDATE);\n+\t\t}\n+\n+done:\n+\t\t/* Unlock head */\n+\t\tunlock_file(head_fd);\n+\t\treturn send_sha1(argv[1], sha1_new);\n+\t\twrite(fd_out, buff, len);\n+\t} else {\n+\t\treturn send_error(argv[1],ERROR_INVALID);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* Return < 0 on I/O error\n+ */\n+static int cmd_request(int argc, char **argv)\n+{\n+\tint err;\n+\n+\tif (argc == 2) {\n+\t\tchar sha1[40];\n+\t\tvoid *data;\n+\t\tunsigned long size;\n+\n+ \t\terr = get_sha1(argv[1], sha1);\n+\n+\t\t/* If sha1 exists, send it. */\n+\t\tif (err < 0)\n+\t\t\treturn send_error(argv[1],ERROR_REQUEST_INVALID);\n+\n+\t\tdata = map_sha1_file(sha1, &size);\n+\t\tif (data == NULL)\n+\t\t\treturn send_error(argv[1],ERROR_REQUEST_INVALID);\n+\n+\t\terr = send_send(sha1, size, data);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n+\t\terr = process_request();\n+\t\tmunmap(data, size);\n+\t} else {\n+\t\terr = send_error(argv[1],ERROR_INVALID);\n+\t}\n+\n+\treturn err;\n+}\n+\n+static int cmd_send(int argc, char **argv)\n+{\n+\tint err;\n+\tint tmpfd = -1;\n+\tchar tmpn[]=\"/tmp/git.daemon.XXXXXX\";\n+\n+\tif (argc == 3) {\n+\t\tchar sha1[20];\n+\t\tint size = strtol(argv[2],NULL,16);\n+\t\tchar type[32];\n+\t\tvoid *buff;\n+\t\tconst char *fname;\n+\t\tint fd;\n+\t\tint exists = 0;\n+\n+ \t\terr = get_sha1(argv[1], sha1);\n+\t\t/* If sha1 exists, just drop all the bytes on the floor */\n+\t\t/* Otherwise, create a temp file, and stuff the bytes there */\n+\n+\t\tif (err == 0) {\n+\t\t\ttmpfd = mkstemp(tmpn);\n+\t\t\tunlink(tmpn);\n+\t\t} else {\n+\t\t\texists = 1;\n+\t\t\ttmpfd = open(\"/dev/null\", O_RDWR);\n+\t\t}\n+\n+\t\terr = write_sha1_from_fd_to_fd(sha1, fd_in, tmpfd);\n+\t\tif (err < 0 || size != err) {\n+\t\t\tclose(tmpfd);\n+\t\t\treturn send_error(argv[1],ERROR_SEND_INVALID);\n+\t\t}\n+\n+\t\tif (exists)\n+\t\t\tgoto done;\n+\n+\t\t/* Verify that the temp file contains a valid blob/tree \n+\t\t * This step also recurses and gets all the 'good stuff'\n+\t\t */\n+\t\terr = verify_file(tmpfd, size, sha1, type);\n+\t\tif (err < 0) {\n+\t\t\tclose(tmpfd);\n+\t\t\treturn send_error(argv[1],ERROR_SEND_INVALID);\n+\t\t}\t\n+\n+\t\t/* Write to database if verified */\n+\t\tbuff = map_file(tmpfd, size);\n+\t\tfname = sha1_file_name(sha1);\n+\t\tfd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);\n+\t\terr = write(fd, buff, size);\n+\t\tclose(fd);\n+\t\tif (err != size) {\n+\t\t\tunlink(fname);\n+\t\t\tclose(tmpfd);\n+\t\t\treturn send_error(argv[1],ERROR_SEND_INVALID);\n+\t\t}\n+\n+done:\n+\t\tclose(tmpfd);\n+\t\treturn send_sha1(NULL, sha1);\n+\t} else {\n+\t\terr = send_error(argv[1],ERROR_INVALID);\n+\t}\n+\n+\treturn err;\n+}\n+\n+int cmd_exists(int argc, char **argv)\n+{\n+\tint err;\n+\n+\tif (argc == 2) {\n+\t\tchar sha1[20];\n+\n+ \t\terr = get_sha1(argv[1], sha1);\n+\n+\t\t/* If sha1 exists, say so. Otherwise say 'send sha1'*/\n+\t\tif (err >= 0)\n+\t\t\treturn send_sha1(NULL, sha1);\n+\n+\t\treturn send_error(NULL, ERROR_REQUEST_INVALID);\n+\t} else {\n+\t\terr = send_error(argv[1],ERROR_INVALID);\n+\t}\n+\n+\treturn err;\n+}\n+\n+int cmd_sha1(int argc, char **argv)\n+{\n+\tint i;\n+\n+\tfprintf(stderr, \"%s\",argv[0]);\n+\tfor ( i=1; i < argc; i++)\n+\t\tfprintf(stderr, \" %s\",argv[i]);\n+\tfprintf(stderr, \"\\n\");\n+\treturn 0;\n+}\n+\n+static int cmd_error(int argc, char **argv)\n+{\n+\tint i;\n+\n+\tfprintf(stderr, \"%s\",argv[0]);\n+\tfor ( i=1; i < argc; i++)\n+\t\tfprintf(stderr, \" %s\",argv[i]);\n+\tfprintf(stderr, \"\\n\");\n+\treturn 0;\n+}\n+\n+static int command(int argc, char **argv)\n+{\n+\tint err;\n+#if 0\n+\tint i;\n+\n+\tfprintf(stderr, \"%s\",argv[0]);\n+\tfor ( i=1; i < argc; i++)\n+\t\tfprintf(stderr, \" %s\",argv[i]);\n+\tfprintf(stderr, \"\\n\");\n+#endif\n+\n+\tif (argc < 1)\n+\t\tgoto invalid;\n+\n+\tif (strcmp(argv[0],\"version\")==0) {\n+\t\terr = cmd_version(argc,argv);\n+\t\treturn err;\n+\t} else if (strcmp(argv[0],\"head\")==0) {\n+\t\terr = cmd_head(argc,argv);\n+\t\treturn err;\n+\t} else if (strcmp(argv[0],\"send\")==0) {\n+\t\terr = cmd_send(argc,argv);\n+\t\treturn err;\n+\t} else if (strcmp(argv[0],\"request\")==0) {\n+\t\terr = cmd_request(argc,argv);\n+\t\treturn err;\n+\t} else if (strcmp(argv[0],\"exists\")==0) {\n+\t\terr = cmd_exists(argc,argv);\n+\t\treturn err;\n+\t} else if (strcmp(argv[0],\"sha1\")==0) {\n+\t\terr = cmd_sha1(argc,argv);\n+\t\treturn err;\n+\t} else if (strcmp(argv[0],\"error\")==0) {\n+\t\terr = cmd_error(argc,argv);\n+\t\treturn err;\n+\t}\n+\n+invalid:\n+\treturn send_error(\"--\",ERROR_INVALID);\n+}\n+\n+/* This *intentionally* drops requests on the floor that are\n+ * larger than sizeof(buffer)\n+ */\n+static int process_request()\n+{\n+\tchar buffer[1024];\n+\tint offset;\n+\tchar **argv,*cp;\n+\tint argc,err;\n+\n+\toffset=0;\n+\n+\twhile (read(fd_in, &buffer[offset], 1)==1) {\n+\t\tif (buffer[offset++]=='\\n')\n+\t\t\tbreak;\n+\t\tif (offset == sizeof(buffer))\n+\t\t\treturn -1;\n+\t}\n+\toffset--;\n+\n+\tif (offset < 0 || buffer[offset]!='\\n')\n+\t\treturn -1;\n+\n+\tbuffer[offset]=0;\n+\targc=0;\n+\targv=xmalloc(sizeof(char *));\n+\n+\tcp = &buffer[0];\n+\twhile (1) {\n+\t\twhile (*cp && isspace(*cp)) cp++;\n+\t\tif (*cp == 0)\n+\t\t\tbreak;\n+\t\targv[argc++]=cp;\n+\t\targv=xrealloc(argv, (argc+1)*sizeof(char *));\n+\t\twhile (*cp && !isspace(*cp)) cp++;\n+\t\tif (*cp == 0)\n+\t\t\tbreak;\n+\t\t*(cp++) = 0;\n+\t};\n+\n+\targv[argc]=NULL;\n+\terr = command(argc,argv);\n+\tfree(argv);\n+\n+\treturn err;\n+}\n+\n+/* Reap children */\n+static void reaper(int sig)\n+{\n+\tint status;\n+\n+\twaitpid(-1, &status, WNOHANG);\n+}\n+\n+static int get_ip_addr(const char *ip, struct in_addr *addr)\n+{\n+\tint err;\n+\tstruct hostent *host;\n+\n+\terr = inet_pton(AF_INET, ip, addr);\n+\tif (err < 0)\n+\t\treturn 0;\n+\n+\thost = gethostbyname(ip);\n+\tif (host == NULL)\n+\t\treturn -1;\n+\n+\treturn inet_pton(AF_INET, host->h_addr, addr);\n+}\n+\n+static int get_port(const char *port)\n+{\n+\tstruct servent *serv;\n+\tint p;\n+\n+\tif (sscanf(port,\"%d\",&p) == 1)\n+\t\treturn p;\n+\n+\tserv = getservbyname(port,\"tcp\");\n+\tif (serv == NULL)\n+\t\treturn -1;\n+\n+\treturn serv->s_port;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tenum {\n+\t\tMODE_STDIO,\n+\t\tMODE_UNIX,\n+\t\tMODE_TCP,\n+\t} mode = MODE_STDIO;\n+\tconst char *port = \"/tmp/.gitd\",*host=\"127.0.0.1\";\n+\tunion {\n+\t\tstruct sockaddr\t   generic;\n+\t\tstruct sockaddr_un un;\n+\t\tstruct sockaddr_in in;\n+\t} sock;\n+\tstruct sockaddr_un *s_unix = (void *)&sock.un;\n+\tstruct sockaddr_in *s_inet = (void *)&sock.in;\n+\tsize_t s_size = 0;\n+\tint max_clients=100, err;\n+\n+\tgit_dir = gitenv(GIT_DIR_ENVIRONMENT) ? : DEFAULT_GIT_DIR_ENVIRONMENT;\n+\n+\targv++;\n+\targc--;\n+\tfor (; argc > 0; argv++, argc--) {\n+\t\tchar *path = argv[0];\n+\n+\t\tif (path[0] != '-')\n+\t\t       break;\n+\n+\t\tif (!strcmp(path,\"--\")) {\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!strcmp(path,\"--unix\")) {\n+\t\t\tmode = MODE_UNIX;\n+\t\t\tcontinue;\n+\t\t}\n+\t\t\n+\t\tif (!strcmp(path,\"--tcp\")) {\n+\t\t\tmode = MODE_TCP;\n+\t\t\tcontinue;\n+\t\t}\n+\t\t\n+\t\tif (!strcmp(path, \"--max-clients\")) {\n+\t\t\tif (argc < 2)\n+\t\t\t\tdie(\"git-daemon: --max-clients <number>\");\n+\t\t\tmax_clients = strtoul(argv[1],NULL,0);\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(path, \"--host\")) {\n+\t\t\tif (argc < 2)\n+\t\t\t\tdie(\"git-daemon: --host <host>\");\n+\t\t\thost = argv[1];\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(path, \"--port\")) {\n+\t\t\tif (argc < 2)\n+\t\t\t\tdie(\"git-daemon: --port <port>\");\n+\t\t\tport = argv[1];\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!strcmp(path, \"--db\")) {\n+\t\t\tif (argc < 2)\n+\t\t\t\tdie(\"git-daemon: --db <path/.git>\");\n+\t\t\tgit_dir = argv[2];\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tcontinue;\n+\t\t}\n+\t}\n+\n+\tswitch (mode) {\n+\t\tcase MODE_STDIO: fd_in = 0; fd_out = 1; break;\n+\t\tcase MODE_UNIX:\n+\t\t\tfd_in = fd_out = socket(PF_UNIX, SOCK_STREAM, 0);\n+\t\t\tif (fd_in < 0)\n+\t\t\t\tdie(\"git-daemon: Can't create local domain socket\");\n+\t\t\tstrncpy(s_unix->sun_path, port, UNIX_PATH_MAX);\n+\t\t\ts_unix->sun_path[UNIX_PATH_MAX-1]=0;\n+\t\t\ts_unix->sun_family = AF_UNIX;\n+\t\t\ts_size = sizeof(*s_unix);\n+\t\t\tbreak;\n+\t\tcase MODE_TCP:\n+\t\t\tfd_in = fd_out = socket(PF_INET, SOCK_STREAM, 0);\n+\t\t\tif (fd_in < 0)\n+\t\t\t\tdie(\"git-daemon: Can't create TCP/IP socket\");\n+\t\t\ts_inet->sin_family = AF_INET;\n+\t\t\terr = get_ip_addr(host, &s_inet->sin_addr);\n+\t\t\ts_inet->sin_port = htons(get_port(port));\n+\t\t\ts_size = sizeof(*s_inet);\n+\t\t\tbreak;\n+\t}\n+\n+\n+\tif (argc > 0) {\n+\t\tif (s_size != 0) {\n+\t\t\terr = connect(fd_in, &sock.generic, s_size);\n+\t\t\tif (err < 0)\n+\t\t\t\tdie(\"git-daemon: Can't connect to socket \\\"%s\\\"\",port);\n+\t\t}\n+\n+\t\terr = send_command(argc, argv);\n+\t\tif (err < 0)\n+\t\t\treturn err;\n+\t\treturn  process_request();\n+        }\n+\n+\tif (s_size != 0) {\n+\t\tint one = 1;\n+\t\terr = setsockopt(fd_in, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));\n+\t\terr = bind(fd_in, &sock.generic, s_size);\n+\t\tlisten(fd_in, max_clients);\n+\t\tdo {\n+\t\t\tsignal(SIGCHLD, reaper);\n+\t\t\tfd_out = accept(fd_in, NULL, NULL);\n+\t\t\tif (fd_out < 0)\n+\t\t\t\tdie(\"git-daemon: Failed to start listening\");\n+\t\t\tif (fork()==0) \n+\t\t\t\tbreak;\n+\t\t\tclose(fd_out);\n+\t\t} while (1);\n+\n+\t\tfd_in = fd_out;\n+\t}\n+\n+\twhile (process_request() >= 0);\n+\n+\treturn 0;\n+}\nonly in patch2:\nunchanged:\n--- /dev/null\n+++ b/Documentation/git-daemon.txt\n@@ -0,0 +1,92 @@\n+git-daemon(1)\n+=============\n+v0.1, May 2005\n+\n+NAME\n+----\n+git-daemon - Client/server for exchanging GIT objects\n+\n+\n+SYNOPSIS\n+--------\n+'git-daemon' [--db <git-db-path>] [--stdio | --tcp | --udp] \n+\t     [--port <port>] [--host <host>] [-- command...]\n+\n+DESCRIPTION\n+-----------\n+\n+OPTIONS\n+-------\n+--db::\n+\tSet the GIT object database path to use\n+\n+--stdio::\n+\tUse stdin/stdout as the transport (default)\n+\n+--tcp::\n+\tUse TCP as the transport\n+\n+--unix::\n+\tUse Unix domain sockets as the transport\n+\n+--host::\n+\tSpecify IPv4 host for --tcp transport\n+\n+--port::\n+\tSpecify IPv4 port for --tcp transport, or the\n+\tfilesystem socket path for the --unix transport\n+\n+--::\n+\tStop argument processing\n+\n+<command>::\n+\tGIT Daemon protocol command\n+\n+GIT Daemon Protocol Commands:\n+-----------------------------\n+\n+version::\n+\tRequests the version string, returned in an error message\n+\tExpects: 'error'\n+\n+head <head-id>::\n+\tRequests SHA1 of the <head-id>\n+\tExpects: 'sha1' or 'error'\n+\n+head <head-id> <old-sha1> <new-sha1>::\n+\tRequests that <head-id> be updated with <new-sha1>. Use\n+\t'--' for <old-sha1> to create a new head.\n+\tExpects: 'sha1', 'request', or 'error'\n+\n+exists <sha1>::\n+\tDetermine if SHA1 exists in remote\n+\tExpects: 'sha1' or 'error'\n+\n+request <sha1>::\n+\tRequest SHA1 object. \n+\tExpects: 'send' or 'error'\n+\n+send <sha1>::\n+\tSend SHA1 object.\n+\tExpects: 'sha1' or 'error'\n+\n+error <key> <hex-code> <error-message>::\n+\tReturned error code\n+\tExpects: Nothing\n+\n+sha1 <key> <hex-sha1>::\n+\tSuccess message for 'head' and 'send' commands.\n+\tExpects: Nothing\n+\n+Author\n+------\n+Written by Jason McMullan <jason.mcmullan@timesys.com>\n+\n+Documentation\n+--------------\n+Documentation by Jason McMullan and the git-list <git@vger.kernel.org>.\n+\n+GIT\n+---\n+Part of the link:git.html[git] suite\n+\n-- \nJason McMullan <jason.mcmullan@timesys.com>\nTimeSys Corporation\n"},{"id":"4495","messageId":"Pine.LNX.4.58.0506030856490.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"20050603152212.GA4598@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T16:02:10Z","receivedAt":"2005-06-03T16:02:10Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, Jason McMullan wrote:\n>\n> git-daemon - Client/server for exchanging GIT objects\n\nHmm.. I'd prefer not calling it a deamon, since if I understand correctly,\nthe _normal_ usage would likely be to use it as\n\n\t.. | ssh .... -e git-deamon\n\nie it wouldn't be a deamon at all, it would be a foreground server. So I'd \ncall it just \"git-server\" or something.\n\nAnyway, technically this looks ok, but I'd hate to apply it until there is \nsomething that actually uses it and an example of that usage.\n\n\t\tLinus\n"},{"id":"4496","messageId":"1117814982.32257.64.camel@jmcmullan.timesys","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506030856490.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"McMullan, Jason","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-03T16:09:41Z","receivedAt":"2005-06-03T16:09:41Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"On Fri, 2005-06-03 at 09:02 -0700, Linus Torvalds wrote:\n> ie it wouldn't be a deamon at all, it would be a foreground server. So I'd \n> call it just \"git-server\" or something.\n\nServer.. Sounds ok. Will do.\n\n> Anyway, technically this looks ok, but I'd hate to apply it until there is \n> something that actually uses it and an example of that usage.\n\nWell, I use it to keep my home and work repos in sync, but yeah,\nusers == 1 doesn't make a good case for inclusion.\n\nI just want to have this out there, because I find rsync a little too\nheavy handed for my taste, and I'm still hesitant about the cg-rpush\nlocking semantics.\n\n-- \nJason McMullan <jason.mcmullan@timesys.com>\nTimeSys Corporation\n\n"},{"id":"4498","messageId":"Pine.LNX.4.58.0506030929150.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"1117814982.32257.64.camel@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T16:30:47Z","receivedAt":"2005-06-03T16:30:47Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, McMullan, Jason wrote:\n> \n> > Anyway, technically this looks ok, but I'd hate to apply it until there is \n> > something that actually uses it and an example of that usage.\n> \n> Well, I use it to keep my home and work repos in sync, but yeah,\n> users == 1 doesn't make a good case for inclusion.\n\nWell, it's fine, but you should at least tell _how_ you use it. What are\nthe scripts you use to synchronize etc etc..\n\nSo when I said \"some_thing_ that actually uses it\", I didn't mean more\n_people_ than you personally, but the scaffolding around it, really.\n\n\t\t\tLinus\n"},{"id":"4499","messageId":"7vr7fjml35.fsf@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506030856490.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-03T17:00:46Z","receivedAt":"2005-06-03T17:00:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> ie it wouldn't be a deamon at all, it would be a foreground server. So I'd \nLT> call it just \"git-server\" or something.\n\nThat particular name risks conflicting name with other\ngit-servers offering different service for git; gitweb is a\ngit-server isn't it?  git-sync might be better fit.\n\nLT> Anyway, technically this looks ok,...\n\nI'd address them in a separate message later today.\n\n"},{"id":"4500","messageId":"1117819137.32257.75.camel@jmcmullan.timesys","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506030929150.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"McMullan, Jason","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-03T17:18:57Z","receivedAt":"2005-06-03T17:18:57Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"On Fri, 2005-06-03 at 09:30 -0700, Linus Torvalds wrote:\n> Well, it's fine, but you should at least tell _how_ you use it. What are\n> the scripts you use to synchronize etc etc..\n\nSorry, here's some use cases (assuming that git-server is running on\n192.168.1.1 port 7777)\n\n###### Create a new local git repo\n\n$ GITCONN=\"--tcp --host 192.168.1.1 --port 7777\"\n$ git-init-db\n$ git-server $GITCONN -- request master\n\n\n\n###### Update local repo to remote's head linux-devel\n\n$ git-server $GITCONN -- request linux-devel\n\n\n###### Create remote head linux-mumble\n\n$ git-server $GITCONN -- head -- linux-mumble\n6678abc8d819abc919a018ca89273091bc98a\n\n\n###### Get remote head's linux-mumble SHA1\n\n$ git-server $GITCONN -- head linux-mumble\nsha1 linux-mumble 6678abc8d819abc919a018ca89273091bc98a\n\n\n###### Set remote head to new SHA1\n\n$ git-server $GITCONN -- head linux-mumble\n6678abc8d819abc919a018ca89273091bc98a\n8389324a9890218bcd9a0193781abc8a183a9\nsha1 linux-mumble 8389324a9890218bcd9a0193781abc8a183a9\n\n(This has the side effect of the server requesting SHA1 objects from the\nclient if they do not exist on the remote repository)\n\n\n-- \nJason McMullan <jason.mcmullan@timesys.com>\nTimeSys Corporation\n\n"},{"id":"4501","messageId":"7vk6lbmk01.fsf@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"20050603152212.GA4598@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-03T17:24:14Z","receivedAt":"2005-06-03T17:24:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Looks very nice.  Some comments.\n\n    diff -u b/daemon.c b/daemon.c\n    --- b/daemon.c\n    +++ b/daemon.c\n------------\n    +\n    +/* Protocol is symmetric, both client and server\n    + * use the same commands.\n    + *\n    + * version\\n -> error -- 0 <Version string>\\n\n    + *\n    + * head <head-id>\\n -> sha1 <head-id> <sha1>\\n\n    + *\n    + * head <head-id> <old-sha1> <new-sha1>\\n -> sha1 <head-id> <new-sha1>\\n\n    + *\n    + * request <sha1>\\n -> send <sha1> <hex-bytes>\\n<bytes...>\n    + *\n    + * send <sha1> <hex-bytes>\\n<bytes...> -> sha1 -- <sha1>\\n\n    + *\n    + * exists <sha1>\\n -> sha1 -- <sha1>\\n\n    + *\n    + * sha1 <any> <sha1>\\n -> no-op\n    + *\n    + * error <key> <hex-code> <error string>\\n -> no-op\n    + *\n    + */\n\nThis is good for the first cut, but I have a latency concern\nabout \"single request - single send\" style of communication.\nThis being a dedicated GIT specific sync mechanism, you may want\nto give more smarts to the server, so that the client can say \"I\nhave these commits as HEADs in my forest, here are their SHA1s,\nnow sync me up to the head you said you have whose SHA1 is\nthis\", implying he has all their HEADs dependents.  Of course\nthis can come later.\n\n------------\n\n    +static int verify_file(int fd, unsigned long mapsize, const unsigned char *sha1, char *type)\n    +{\n    +\tvoid *map, *buffer;\n   ~~~ \n    +\t\tif (buffer && !strcmp(type, \"delta\")) {\n    +\t\t\tvoid *ref = NULL, *delta = buffer;\n    +\t\t\tunsigned long ref_size, delta_size = size;\n    +\t\t\tbuffer = NULL;\n   ~~~\n    +\t\t\tbuffer = patch_delta(ref, ref_size,\n    +\t\t\t\t\t  delta+20, delta_size-20, \n    +\t\t\t\t\t  &size);\n    +\t\t\tfree(delta);\n    +\t\t\tfree(ref);\n    +\t\t}\n\nA possibility is to chuck the above special case for \"delta\",\nand instead introduce \"delta\" subclass in struct object family\nand make the base object of \"delta\" simply one object on the\nobj->refs list on such a \"delta\" object.  I would imagine that\nthis would let you reuse the sha1_retrieve() loop that you\nalready do for \"commit\", \"tree\", and \"tag\".\n\n    +\t\tif (!strcmp(type, \"blob\")) {\n    +\t\t\tstruct blob *blob = lookup_blob(sha1);\n    +\t\t\tparse_blob_buffer(blob, buffer, size);\n   ~~~\n    +\t\t\tobj = &tag->object;\n    +\t\t} else {\n    +\t\t\tobj = NULL;\n    +\t\t}\n    +\n    +\t\tfree(buffer);\n    +\n    +\t\tif (obj) {\n    +\t\t\tstruct object_list *refs;\n    +\n    +\t\t\tfor (refs = obj->refs; refs ; refs = refs->next) {\n    +\t\t\t\terr = sha1_retrieve(refs->item->sha1);\n    +\t\t\t\tif (err < 0)\n    +\t\t\t\t\treturn err;\n    +\t\t\t}\n    +\t\t\n    +\t\t\treturn 0;\n    +\t\t}\n    +\n    +\t}\n    +\treturn -1;\n    +}\n\n------------\n\n    +static int send_send(const unsigned char *sha1, int size, void *data)\n    +{\n   ~~~\n    +}\n   ~~~\n    +static int cmd_request(int argc, char **argv)\n    +{\n    +\tint err;\n    +\n    +\tif (argc == 2) {\n    +\t\tchar sha1[40];\n    +\t\tvoid *data;\n    +\t\tunsigned long size;\n   ~~~\n    +\t\terr = send_send(sha1, size, data);\n    +\t\tif (err < 0)\n    +\t\t\treturn err;\n\nBy definition, size of SHA1 blob is \"unsigned long\" so\nsend_send() should take such not \"int\".\n\n"},{"id":"4502","messageId":"Pine.LNX.4.58.0506031035470.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"1117819137.32257.75.camel@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T17:41:41Z","receivedAt":"2005-06-03T17:41:41Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, McMullan, Jason wrote:\n> \n> ###### Create a new local git repo\n> \n> $ GITCONN=\"--tcp --host 192.168.1.1 --port 7777\"\n> $ git-init-db\n> $ git-server $GITCONN -- request master\n\nOk. Am I to understand that I could do a push to a remote server with ssh \nusing something like\n\n\tgit-server -- send master |\n\t\tssh master.kernel.org git-server --db /pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nor what?\n\nAlso, how do I send tags?\n\n\t\t\tLinus\n"},{"id":"4503","messageId":"Pine.LNX.4.58.0506031050080.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"7vr7fjml35.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T17:50:23Z","receivedAt":"2005-06-03T17:50:23Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, Junio C Hamano wrote:\n> \n> That particular name risks conflicting name with other\n> git-servers offering different service for git; gitweb is a\n> git-server isn't it?  git-sync might be better fit.\n\nYeah, you're right.\n\n\t\tLinus\n"},{"id":"4504","messageId":"7vmzq7l2cn.fsf@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"7vk6lbmk01.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-daemon server","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-03T18:30:48Z","receivedAt":"2005-06-03T18:30:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"JCH\" == Junio C Hamano <junkio@cox.net> writes:\n\nJCH> Looks very nice.  Some comments.\n\nJCH> This being a dedicated GIT specific sync mechanism, you may want\nJCH> to give more smarts to the server, so that the client can say \"I\nJCH> have these commits as HEADs in my forest, here are their SHA1s,\nJCH> now sync me up to the head you said you have whose SHA1 is\nJCH> this\", implying he has all their HEADs dependents.  Of course\nJCH> this can come later.\n\nAbout the protocol, here is one change you may want to have even\nin the initial version to futureproof yourself, and let you make\na \"low hanging fruit\" optimization without bumping the protocol\nversion up.\n\nMake \"request\" capable to optionally have this format:\n\n\trequest <sha1> <commit-sha1> <ce-path>\n\nNote.  You have to make sure you have some way to quote embedded\nnewlines in ce-path since your protocol is mostly line based.\n\nWhen this optional form is used, the requestor is telling the\nresponder the following:\n\n    (1) it wants to retrieve <sha1>; this is the same as a\n        request without the optional two fields.\n\n    (2) it wants <sha1> because it is trying to complete a tree\n        associated with <commit-sha1>; it already has the commit\n        object itself and knows what the parents of the commit\n        are.\n\n    (3) it already has trees and blobs associated with all the\n        parents of <commit-sha1>.\n\n    (4) it knows that <sha1> resides at <ce-path> in the tree\n        associated with <commit-sha1>.  As a special case, \"\"\n        (an empty string) as <ce-path> means \"the root level\n        tree object associated with <commit-sha1>\".\n\nThe initial implementation of a requestor does not even send\nthis extended form.  The initial implementation of a responder\nmust be able to parse this extended form, but it does not have\nto do anything special about it; just do what your cmd_request()\ncurrently does.  However, this extended request lets your later\nimplementation of the responder create and send delta on the\nfly, by:\n\n    (0) Look at <sha1> in the local storage.  If it is already\n        deltified, do not do anything special but just send it\n        out.\n\n    (1) Look at <commit-sha1> and its parents.  Compare the\n        object (either a blob or a tree) that corresponds to\n        <ce-path> in the trees associated with these commits.\n        Verify <sha1> is indeed what the requestor thinks it is\n        while you are at it.\n\n    (2) Try to synthesize a reasonable delta to create <sha1>\n        based on the objects you find in step (1).  Upon finding\n        a reasonable delta, send that as a delta object to the\n        requestor.  Optionally you may want to replace the\n        <sha1> found at the local store in step (0) with this\n        delta.  If you have many parents, this \"reasonable\"\n        delta does not necessarily have to be the minimal delta.\n\nUnlike a full-blown \"ihave/sendme\" protocol extension, this does\nnot require responder side to keep much client state, and should\ngive you the ability to create and send a reasonable if not\nminimum delta lazily.\n\nHmm.\n\n"},{"id":"4505","messageId":"1117827011.8970.2.camel@jmcmullan.timesys","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031035470.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"McMullan, Jason","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-03T19:30:10Z","receivedAt":"2005-06-03T19:30:10Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"On Fri, 2005-06-03 at 10:41 -0700, Linus Torvalds wrote: \n> Ok. Am I to understand that I could do a push to a remote server with ssh \n> using something like\n> \n> \tgit-server -- send master |\n> \t\tssh master.kernel.org git-server --db /pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nNo, but you could do:\n\n$ ssh master.kernel.org -L 7777:localhost:7777 \\\n    git-server --tcp --port 7777 \\\n               --db /pub/scm/linux/kernel/git/torvalds/linux-2.6.git &\n$ git-server --tcp --port 7777 send master\n\n\nYou could probably play some games with shell redirection to file\ndescriptors if you really wanted to use the stdio stuff over ssh,\nbut that's a little ugly.\n\n\n> Also, how do I send tags?\n\nTags are on my 'TODO' list, as are the deltafication and\nmulitple-request changes. Also, a verdict on the name\n(daemon vs server vs anything else) would be nice.\n\n-- \nJason McMullan <jason.mcmullan@timesys.com>\nTimeSys Corporation\n\n"},{"id":"4506","messageId":"Pine.LNX.4.58.0506031320190.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"1117827011.8970.2.camel@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T20:25:20Z","receivedAt":"2005-06-03T20:25:20Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, McMullan, Jason wrote:\n> \n> No, but you could do:\n\nThat doth suck. Is there any reason for not allowing stdin/stdout as the\ntransfer protocol?\n\nMaking games like having ssh pipe things through is what I already have to \ndo with mail, and it's ok for long-running servers, but I really think of \na \"git pull\" as an _event_.\n\nSo why doesn't stdin/stdout work with ssh, even though the docs say that\nit's even the default?\n\n\t\tLinus\n"},{"id":"4507","messageId":"1117832172.8970.22.camel@jmcmullan.timesys","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031320190.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"McMullan, Jason","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-03T20:56:11Z","receivedAt":"2005-06-03T20:56:11Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"Linus, you were wondering why stdin/stdout was the default, even though\nI don't have a use case for ssh with stdin/stdout:\n\n1) I used the stdin/stdout stuff as debugging\n\n2) It works with xinetd\n\n3) Because I can't figure out how to get /bin/sh to give me two pipes\n   that hook together two processes. What I really want:\n\nssh user@remote git server --db /my/git.git <|> git server request HEAD\n\nWhere 'xxx <|>  yyy' means:\n\n\tTake process xxx's stdin, hook it to yyy's stdout,\n\tTake process yyy's stdin, hook it to xxx's stdout,\n\tRun till they both die.\n\nIf you know how to do that, I'd be grateful.\n\n-- \nJason McMullan <jason.mcmullan@timesys.com>\nTimeSys Corporation\n\n"},{"id":"4508","messageId":"Pine.LNX.4.21.0506031727400.30848-100000@iabervon.org","threadId":"821","inReplyTo":"20050603152212.GA4598@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-06-03T21:33:13Z","receivedAt":"2005-06-03T21:33:13Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Fri, 3 Jun 2005, Jason McMullan wrote:\n\n> git-daemon - Client/server for exchanging GIT objects\n\nIs this somehow different from rpush/rpull aside from using an\nexternally-provided socket and having the proper locking for writing refs\n(which I posted a while ago, but which hasn't been included anywhere yet)?\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"4509","messageId":"Pine.LNX.4.58.0506031410560.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"1117832172.8970.22.camel@jmcmullan.timesys","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T21:38:46Z","receivedAt":"2005-06-03T21:38:46Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, McMullan, Jason wrote:\n> \n> 1) I used the stdin/stdout stuff as debugging\n> \n> 2) It works with xinetd\n> \n> 3) Because I can't figure out how to get /bin/sh to give me two pipes\n>    that hook together two processes. What I really want:\n> \n> ssh user@remote git server --db /my/git.git <|> git server request HEAD\n\nOk, so a ssh connection _would_ work per se, and the only real issue is\nthe pipe itself is one-directional as done by the shell?\n\n> Where 'xxx <|>  yyy' means:\n> \n> \tTake process xxx's stdin, hook it to yyy's stdout,\n> \tTake process yyy's stdin, hook it to xxx's stdout,\n> \tRun till they both die.\n> \n> If you know how to do that, I'd be grateful.\n\nYeah, you're right, you can't do bi-directional piping with shell, and \nyou'd need to do it inside your program. It should be easy enough to do \nwith something like adding a new flag that says \"--exec\", and when seeing \nthat, doing something like\n\n\tif (!strcmp(argv[i], \"--exec\")) {\n\t\tint fd[2][2];\n\t\tpid_t pid;\n\n\t\tif (pipe(fd[0]) < 0 || pipe(fd[1]) < 0)\n\t\t\tdie(\"unable to create pipes\");\n\t\tpid = fork();\n\t\tif (pid < 0)\n\t\t\tdie(\"unable to fork exec process\");\n\n\t\tif (!pid) {\n\t\t\tdup2(fd[0][0], 0);\n\t\t\tdup2(fd[1][1], 1);\n\t\t\tclose_pipes(fd);\n\t\t\texit(system(argv[i+1]));\n\t\t}\n\t\tdup2(fd[1][0], 0);\n\t\tdup2(fd[0][1], 1);\n\t\tclose_pipes(fd);\n\t}\n\nwhere \"close_pipes()\" just looks like\n\n\tvoid close_pipes(int *fd)\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < 3; i++)\n\t\t\tclose(fd[i]);\n\t}\n\nand as usual, the above is totally and utterly untested. And using \n\"system()\" is cheezy and does an extra unnecessary fork(), so if you want \nto, it could be better done with just a \"execve(/bin/sh -c 'string')\" \napproach by hand.\n\nAnyway, with _something_ like the above you could do something like\n\n\tgit-sync --exec \"ssh master.kernel.org git-sync\" ....\n\nand it would do the obvious thing.\n\nWhat do you think?\n\n\t\tLinus\n\n"},{"id":"4512","messageId":"Pine.LNX.4.58.0506031450190.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"Pine.LNX.4.21.0506031727400.30848-100000@iabervon.org","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-03T21:59:38Z","receivedAt":"2005-06-03T21:59:38Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Fri, 3 Jun 2005, Daniel Barkalow wrote:\n> \n> Is this somehow different from rpush/rpull aside from using an\n> externally-provided socket and having the proper locking for writing refs\n> (which I posted a while ago, but which hasn't been included anywhere yet)?\n\nDeathmatch! \n\nAnyway, I have to admit that at least as far as I'm concerned, the \nrpull/rpush thing has the same issues as Jason's code - I've not seen the \nusage documented anywhere, and that's the only real reason I don't use it \nmyself.\n\nAlso, just out of interest, do either or both of these things pipeline the\ntransfer?\n\nMe, I want to have a fairly simple script that does the equivalent of what\nI do now for pushing:\n\n\trsync -av --delete --exclude-from=.exclude .git/ master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nexcept I'd want it to do the locking and the \"only accept trivial pushes\" \nstuff (ie no merging, just a pure update).\n\nMaybe git-rpush does this already, and I just never realized.\n\n\t\tLinus\n"},{"id":"4513","messageId":"f0796bb7050603150168c1db95@mail.gmail.com","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031410560.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"Daniel Serpell","fromEmail":"daniel.serpell@gmail.com","sentAt":"2005-06-03T22:01:06Z","receivedAt":"2005-06-03T22:01:06Z","isPatch":true,"sender":{"key":"daniel.serpell@gmail.com","avatar":null},"body":"On 6/3/05, Linus Torvalds <torvalds@osdl.org> wrote:\n> \n> On Fri, 3 Jun 2005, McMullan, Jason wrote:\n> >\n> > 3) Because I can't figure out how to get /bin/sh to give me two pipes\n> >    that hook together two processes. What I really want:\n> >\n> > ssh user@remote git server --db /my/git.git <|> git server request HEAD\n> \n> Ok, so a ssh connection _would_ work per se, and the only real issue is\n> the pipe itself is one-directional as done by the shell?\n> \n[...]\n> Anyway, with _something_ like the above you could do something like\n> \n>         git-sync --exec \"ssh master.kernel.org git-sync\" ....\n> \n> and it would do the obvious thing.\n> \n\nI would prefer a command line more like the rsync one:\n       git-sync master.kernel.org:directory  ....\n\nOr:\n       git-sync :ssh:master.kernel.org:directory  ....\n\nOr \"uri like\":\n       git-sync ssh://mylogin@master.kernel.org/directory  ....\n\nIt seems much easier, and I suppose that SSH should be the\ndefault \"developer\" protocol.\n\n     Daniel.\n"},{"id":"4516","messageId":"20050603223950.GA13093@pasky.ji.cz","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031450190.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"Petr Baudis","fromEmail":"pasky@ucw.cz","sentAt":"2005-06-03T22:39:50Z","receivedAt":"2005-06-03T22:39:50Z","isPatch":true,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Fri, Jun 03, 2005 at 11:59:38PM CEST, I got a letter\nwhere Linus Torvalds <torvalds@osdl.org> told me that...\n> Anyway, I have to admit that at least as far as I'm concerned, the \n> rpull/rpush thing has the same issues as Jason's code - I've not seen the \n> usage documented anywhere, and that's the only real reason I don't use it \n> myself.\n\nFWIW, Cogito's cg-pull can use rpull/rpush (if your branch URLs use the\ngit+ssh scheme), and I've seen people actually using it.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nC++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor\n"},{"id":"4522","messageId":"Pine.LNX.4.21.0506031927000.30848-100000@iabervon.org","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031450190.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-06-04T00:06:51Z","receivedAt":"2005-06-04T00:06:51Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Fri, 3 Jun 2005, Linus Torvalds wrote:\n\n> \n> \n> On Fri, 3 Jun 2005, Daniel Barkalow wrote:\n> > \n> > Is this somehow different from rpush/rpull aside from using an\n> > externally-provided socket and having the proper locking for writing refs\n> > (which I posted a while ago, but which hasn't been included anywhere yet)?\n> \n> Deathmatch! \n> \n> Anyway, I have to admit that at least as far as I'm concerned, the \n> rpull/rpush thing has the same issues as Jason's code - I've not seen the \n> usage documented anywhere, and that's the only real reason I don't use it \n> myself.\n\nSee below. I'd foolishly explained http-pull and rpull, but neglected to\nmention that rpush is actually useful in its own right. It is used in\nessentially the same way, but on the other computer. (And I need to fix\nthe Documentation/ file, since other people seem to have missed it, too)\n\n> Also, just out of interest, do either or both of these things pipeline the\n> transfer?\n\nMine doesn't currently. The protocol supports a low level of pipelining\n(you can request all the objects you know you want, and the sending side\ndoesn't care that you're sending requests before the previous ones are\nsatisfied), but I haven't figured out (or found out from Matt, more\nlikely) a good way to negotiate something more clever.\n\n> Me, I want to have a fairly simple script that does the equivalent of what\n> I do now for pushing:\n> \n> \trsync -av --delete --exclude-from=.exclude .git/ master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n> \n> except I'd want it to do the locking and the \"only accept trivial pushes\" \n> stuff (ie no merging, just a pure update).\n\nWith patches I have (but have to rebase and such), you could do:\n\ngit-rpush -a -w heads/master heads/master //master.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nThis would only send the heads/master file and all of the object files it\nreferences. It would be easy to write a \"--old heads/linus\" which would\nrequire that the remote value was the local value of heads/linus (I.e.,\nthe public value of your head that you'd been working from).\n\n> Maybe git-rpush does this already, and I just never realized.\n\nIt currently does all the objects, but doesn't write the refs file on the\nremote end. That is:\n\n  git-rpush -a heads/master //master.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nWill cause the public tree to contain all the objects reachable from the\nlocal value of heads/master. Then you need to write the new head by hand\nif you don't have the newer stuff.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"4562","messageId":"7vk6l9flzr.fsf@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"Pine.LNX.4.21.0506031927000.30848-100000@iabervon.org","subject":"Re: [PATCH] git-daemon server","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-05T04:47:36Z","receivedAt":"2005-06-05T04:47:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"DB\" == Daniel Barkalow <barkalow@iabervon.org> writes:\n\nDB> With patches I have (but have to rebase and such), you could do:\n\nDB> git-rpush -a -w heads/master heads/master //master.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n\nI'd like to see your \"-w\" extention merged into mainline soon\n(both push and pull).\n\nBTW, don't we want to have them renamed to git-ssh-pull (and\ngit-ssh-push) for consistency with other transports, before 1.0\nhappens?\n\n\n\n"},{"id":"4563","messageId":"Pine.LNX.4.21.0506050132590.30848-100000@iabervon.org","threadId":"821","inReplyTo":"7vk6l9flzr.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-daemon server","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-06-05T05:38:17Z","receivedAt":"2005-06-05T05:38:17Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 4 Jun 2005, Junio C Hamano wrote:\n\n> I'd like to see your \"-w\" extention merged into mainline soon\n> (both push and pull).\n\nI have the patches worked out now, and I'm planning to send them on\nMonday.\n\n> BTW, don't we want to have them renamed to git-ssh-pull (and\n> git-ssh-push) for consistency with other transports, before 1.0\n> happens?\n\nI think that would be good, but I'm still using a really old version of\ngit for my development, so I don't have your diff rename support; could\nyou send a patch to do it?\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"4565","messageId":"7vzmu5b8o6.fsf@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"Pine.LNX.4.21.0506050132590.30848-100000@iabervon.org","subject":"Re: [PATCH] git-daemon server","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-05T06:48:57Z","receivedAt":"2005-06-05T06:48:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"DB\" == Daniel Barkalow <barkalow@iabervon.org> writes:\n\nDB> On Sat, 4 Jun 2005, Junio C Hamano wrote:\n\n>> BTW, don't we want to have them renamed to git-ssh-pull (and\n>> git-ssh-push) for consistency with other transports, before 1.0\n>> happens?\n\nDB> I think that would be good, but I'm still using a really old version of\nDB> git for my development, so I don't have your diff rename support; could\nDB> you send a patch to do it?\n\nI am sorry, but you lost me.  I am afraid that I do not\nunderstand what you are asking me to send you: a patch to do\nwhat?  Tell your old git how to do -M/-C?  That would be \"the\ntip of Linus repository\"...\n\nAh (lightbulb!), are you asking me to send the patch in the\ngit-extended rename diff format, like this?\n\n    $ git-diff-cache -p -B -C HEAD\n    diff --git a/Documentation/git-rpull.txt b/Documentation/git-ssh-pull.txt\n    similarity index 89%\n    rename old Documentation/git-rpull.txt\n    rename new Documentation/git-ssh-pull.txt\n    --- a/Documentation/git-rpull.txt\n    +++ b/Documentation/git-ssh-pull.txt\n    @@ -1,20 +1,20 @@\n    -git-rpull(1)\n    -============\n    +git-ssh-pull(1)\n    +===============\n     v0.1, May 2005\n    ...\n\nI am not sure if this is suitable for patch submission.  I did\nthe rename/copy stuff mostly for software archaeology purposes\n(meaning, you examine what is in your repository), not to\ngenerate patches for submission via e-mail.\n\nIt certainly is a good test for the git-apply stuff Linus has\nbeen working on, and in addition it would have a good amusement\nvalue to see how well it would work (or how badly it would barf\n;-), but I suspect Linus (or, rather, his \"dotest\" script) would\nappreciate it more if it came in the traditional diff format\nthat does not use the rename stuff.  I dunno.  Let's ask Linus\nfirst.\n\nLinus, can your workflow grok things like this, or do you prefer\npatch submission to use traditional diff format without renames?\n\n"},{"id":"4566","messageId":"7vfyvxb89m.fsf_-_@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"Pine.LNX.4.21.0506050132590.30848-100000@iabervon.org","subject":"[PATCH-CAREFUL/RENAME] rename git-rpush and git-rpull to git-ssh-push and git-ssh-pull","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-05T06:57:41Z","receivedAt":"2005-06-05T06:57:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"In preparation for 1.0 release, this make the command names\nconsistent with others in git-*-pull family.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n*** Linus, please be careful with this patch.  This uses\n*** extended git \"rename\" diff format, and I doubt that\n*** traditional patch -p1 would do the right thing.  I am\n*** sending it because Dan asked me to, and also it may serve as\n*** a good example if your plan is to support git extended diff\n*** format in your \"dotest\" toolchain.  I'll send the same patch\n*** in the traditional diff format in a separate message.\n\n Documentation/git-ssh-pull.txt |   10 +++++-----\n Documentation/git-ssh-push.txt |   10 +++++-----\n Documentation/git.txt          |    6 +++---\n Makefile                       |    6 +++---\n ssh-pull.c                     |    4 ++--\n ssh-push.c                     |   14 +++++++-------\n 6 files changed, 25 insertions(+), 25 deletions(-)\n\ngit-diff-cache -p -B -C HEAD\ndiff --git a/Documentation/git-rpull.txt b/Documentation/git-ssh-pull.txt\nsimilarity index 89%\nrename old Documentation/git-rpull.txt\nrename new Documentation/git-ssh-pull.txt\n--- a/Documentation/git-rpull.txt\n+++ b/Documentation/git-ssh-pull.txt\n@@ -1,20 +1,20 @@\n-git-rpull(1)\n-============\n+git-ssh-pull(1)\n+===============\n v0.1, May 2005\n \n NAME\n ----\n-git-rpull - Pulls from a remote repository over ssh connection\n+git-ssh-pull - Pulls from a remote repository over ssh connection\n \n \n \n SYNOPSIS\n --------\n-'git-rpull' [-c] [-t] [-a] [-d] [-v] commit-id url\n+'git-ssh-pull' [-c] [-t] [-a] [-d] [-v] commit-id url\n \n DESCRIPTION\n -----------\n-Pulls from a remote repository over ssh connection, invoking git-rpush on\n+Pulls from a remote repository over ssh connection, invoking git-ssh-push on\n the other end.\n \n OPTIONS\ndiff --git a/Documentation/git-rpush.txt b/Documentation/git-ssh-push.txt\nsimilarity index 71%\nrename old Documentation/git-rpush.txt\nrename new Documentation/git-ssh-push.txt\n--- a/Documentation/git-rpush.txt\n+++ b/Documentation/git-ssh-push.txt\n@@ -1,19 +1,19 @@\n-git-rpush(1)\n-============\n+git-ssh-push(1)\n+===============\n v0.1, May 2005\n \n NAME\n ----\n-git-rpush - Helper \"server-side\" program used by git-rpull\n+git-ssh-push - Helper \"server-side\" program used by git-ssh-pull\n \n \n SYNOPSIS\n --------\n-'git-rpush'\n+'git-ssh-push'\n \n DESCRIPTION\n -----------\n-Helper \"server-side\" program used by git-rpull.\n+Helper \"server-side\" program used by git-ssh-pull.\n \n \n Author\ndiff --git a/Documentation/git.txt b/Documentation/git.txt\n--- a/Documentation/git.txt\n+++ b/Documentation/git.txt\n@@ -148,7 +148,7 @@ link:git-resolve-script.html[git-resolve\n link:git-tag-script.html[git-tag-script]::\n \tAn example script to create a tag object signed with GPG\n \n-link:git-rpull.html[git-rpull]::\n+link:git-ssh-pull.html[git-ssh-pull]::\n \tPulls from a remote repository over ssh connection\n \n Interogators:\n@@ -156,8 +156,8 @@ Interogators:\n link:git-diff-helper.html[git-diff-helper]::\n \tGenerates patch format output for git-diff-*\n \n-link:git-rpush.html[git-rpush]::\n-\tHelper \"server-side\" program used by git-rpull\n+link:git-ssh-push.html[git-ssh-push]::\n+\tHelper \"server-side\" program used by git-ssh-pull\n \n \n \ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -30,7 +30,7 @@ PROG=   git-update-cache git-diff-files \n \tgit-checkout-cache git-diff-tree git-rev-tree git-ls-files \\\n \tgit-check-files git-ls-tree git-merge-base git-merge-cache \\\n \tgit-unpack-file git-export git-diff-cache git-convert-cache \\\n-\tgit-http-pull git-rpush git-rpull git-rev-list git-mktag \\\n+\tgit-http-pull git-ssh-push git-ssh-pull git-rev-list git-mktag \\\n \tgit-diff-helper git-tar-tree git-local-pull git-write-blob \\\n \tgit-get-tar-commit-id git-mkdelta git-apply git-stripspace\n \n@@ -105,8 +105,8 @@ git-diff-cache: diff-cache.c\n git-convert-cache: convert-cache.c\n git-http-pull: http-pull.c pull.c\n git-local-pull: local-pull.c pull.c\n-git-rpush: rsh.c\n-git-rpull: rsh.c pull.c\n+git-ssh-push: rsh.c\n+git-ssh-pull: rsh.c pull.c\n git-rev-list: rev-list.c\n git-mktag: mktag.c\n git-diff-helper: diff-helper.c\ndiff --git a/rpull.c b/ssh-pull.c\nsimilarity index 97%\nrename old rpull.c\nrename new ssh-pull.c\n--- a/rpull.c\n+++ b/ssh-pull.c\n@@ -62,13 +62,13 @@ int main(int argc, char **argv)\n \t\targ++;\n \t}\n \tif (argc < arg + 2) {\n-\t\tusage(\"git-rpull [-c] [-t] [-a] [-v] [-d] commit-id url\");\n+\t\tusage(\"git-ssh-pull [-c] [-t] [-a] [-v] [-d] commit-id url\");\n \t\treturn 1;\n \t}\n \tcommit_id = argv[arg];\n \turl = argv[arg + 1];\n \n-\tif (setup_connection(&fd_in, &fd_out, \"git-rpush\", url, arg, argv + 1))\n+\tif (setup_connection(&fd_in, &fd_out, \"git-ssh-push\", url, arg, argv + 1))\n \t\treturn 1;\n \n \tif (get_version())\ndiff --git a/rpush.c b/ssh-push.c\nsimilarity index 93%\nrename old rpush.c\nrename new ssh-push.c\n--- a/rpush.c\n+++ b/ssh-push.c\n@@ -16,7 +16,7 @@ int serve_object(int fd_in, int fd_out) \n \tdo {\n \t\tsize = read(fd_in, sha1 + posn, 20 - posn);\n \t\tif (size < 0) {\n-\t\t\tperror(\"git-rpush: read \");\n+\t\t\tperror(\"git-ssh-push: read \");\n \t\t\treturn -1;\n \t\t}\n \t\tif (!size)\n@@ -30,7 +30,7 @@ int serve_object(int fd_in, int fd_out) \n \tbuf = map_sha1_file(sha1, &objsize);\n \t\n \tif (!buf) {\n-\t\tfprintf(stderr, \"git-rpush: could not find %s\\n\", \n+\t\tfprintf(stderr, \"git-ssh-push: could not find %s\\n\", \n \t\t\tsha1_to_hex(sha1));\n \t\tremote = -1;\n \t}\n@@ -45,9 +45,9 @@ int serve_object(int fd_in, int fd_out) \n \t\tsize = write(fd_out, buf + posn, objsize - posn);\n \t\tif (size <= 0) {\n \t\t\tif (!size) {\n-\t\t\t\tfprintf(stderr, \"git-rpush: write closed\");\n+\t\t\t\tfprintf(stderr, \"git-ssh-push: write closed\");\n \t\t\t} else {\n-\t\t\t\tperror(\"git-rpush: write \");\n+\t\t\t\tperror(\"git-ssh-push: write \");\n \t\t\t}\n \t\t\treturn -1;\n \t\t}\n@@ -71,7 +71,7 @@ void service(int fd_in, int fd_out) {\n \t\tretval = read(fd_in, &type, 1);\n \t\tif (retval < 1) {\n \t\t\tif (retval < 0)\n-\t\t\t\tperror(\"rpush: read \");\n+\t\t\t\tperror(\"ssh-push: read \");\n \t\t\treturn;\n \t\t}\n \t\tif (type == 'v' && serve_version(fd_in, fd_out))\n@@ -91,12 +91,12 @@ int main(int argc, char **argv)\n                 arg++;\n         }\n         if (argc < arg + 2) {\n-\t\tusage(\"git-rpush [-c] [-t] [-a] commit-id url\");\n+\t\tusage(\"git-ssh-push [-c] [-t] [-a] commit-id url\");\n                 return 1;\n         }\n \tcommit_id = argv[arg];\n \turl = argv[arg + 1];\n-\tif (setup_connection(&fd_in, &fd_out, \"git-rpull\", url, arg, argv + 1))\n+\tif (setup_connection(&fd_in, &fd_out, \"git-ssh-pull\", url, arg, argv + 1))\n \t\treturn 1;\n \n \tservice(fd_in, fd_out);\n\n\n"},{"id":"4576","messageId":"Pine.LNX.4.21.0506051150440.30848-100000@iabervon.org","threadId":"821","inReplyTo":"7vzmu5b8o6.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-daemon server","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-06-05T16:03:41Z","receivedAt":"2005-06-05T16:03:41Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 4 Jun 2005, Junio C Hamano wrote:\n\n> Ah (lightbulb!), are you asking me to send the patch in the\n> git-extended rename diff format, like this?\n> \n>     $ git-diff-cache -p -B -C HEAD\n>     diff --git a/Documentation/git-rpull.txt b/Documentation/git-ssh-pull.txt\n>     similarity index 89%\n>     rename old Documentation/git-rpull.txt\n>     rename new Documentation/git-ssh-pull.txt\n>     --- a/Documentation/git-rpull.txt\n>     +++ b/Documentation/git-ssh-pull.txt\n>     @@ -1,20 +1,20 @@\n>     -git-rpull(1)\n>     -============\n>     +git-ssh-pull(1)\n>     +===============\n>      v0.1, May 2005\n>     ...\n\nRight. I hadn't actually been following the discussion entirely, but it\ncertainly seems like one major benefit of the rename/copy stuff is that it\nwill generate more readable diffs. That is, I can see what you changed in\nthe process of renaming the file, and don't have to inspect all the lines\nyou didn't change to see that they're the same.\n\n> I am not sure if this is suitable for patch submission.  I did\n> the rename/copy stuff mostly for software archaeology purposes\n> (meaning, you examine what is in your repository), not to\n> generate patches for submission via e-mail.\n\nI think that examination by mailing list subscribers is a very similar\nsituation, and it makes sense to apply exactly the patch that has been\nchecked.\n\n> It certainly is a good test for the git-apply stuff Linus has\n> been working on, and in addition it would have a good amusement\n> value to see how well it would work (or how badly it would barf\n> ;-), but I suspect Linus (or, rather, his \"dotest\" script) would\n> appreciate it more if it came in the traditional diff format\n> that does not use the rename stuff.  I dunno.  Let's ask Linus\n> first.\n\nI think I like best what you actually did: send it both ways. Having a \ntest case that's a real change someone wants to make as well as a\nreference for how it should come out helps a lot in debugging. And I can\ntell that the rename-using version is what I wanted, and the\nnon-rename-using version is also must be good if the results match.\n\n\t-Daniel\n*This .sig left intentionally blank*\n\n"},{"id":"4577","messageId":"Pine.LNX.4.21.0506051203510.30848-100000@iabervon.org","threadId":"821","inReplyTo":"7vfyvxb89m.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH-CAREFUL/RENAME] rename git-rpush and git-rpull to git-ssh-push and git-ssh-pull","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-06-05T16:06:25Z","receivedAt":"2005-06-05T16:06:25Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 4 Jun 2005, Junio C Hamano wrote:\n\n> In preparation for 1.0 release, this make the command names\n> consistent with others in git-*-pull family.\n> \n> Signed-off-by: Junio C Hamano <junkio@cox.net>\n\nThis looks right to me (assuming git-apply produces the expected results,\nof course).\n\nAcked-by: Daniel Barkalow <barkalow@iabervon.org>\n\n\n"},{"id":"4579","messageId":"Pine.LNX.4.58.0506050914030.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"7vzmu5b8o6.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-05T16:17:13Z","receivedAt":"2005-06-05T16:17:13Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 4 Jun 2005, Junio C Hamano wrote:\n> \n> Linus, can your workflow grok things like this, or do you prefer\n> patch submission to use traditional diff format without renames?\n\nI haven't made \"git-apply\" do the final part yet: it doesn't actually \napply anything. So I'm still using standard patch in my workflow.\n\nBut that's largely been because I haven't been hugely motivated to fixing \nit yet. I will now correct that.\n\nLet's see if I can do the last mile now.\n\n\t\tLinus\n"},{"id":"4582","messageId":"1117989877.10424.10.camel@port.evillabs.net","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031410560.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"Jason McMullan","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-05T16:44:37Z","receivedAt":"2005-06-05T16:44:37Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"On Fri, 2005-06-03 at 14:38 -0700, Linus Torvalds wrote:\n> Anyway, with _something_ like the above you could do something like\n> \n> \tgit-sync --exec \"ssh master.kernel.org git-sync\" ....\n> \n> and it would do the obvious thing.\n\nSounds good. I'll implement that right after I put in tags support, and\nmerge by verify-before-write pull mechanism into pull.c, so everyone\ncan use it.\n\nAnd, it looks like 'git-sync' is the decided name? Excellent!\n"},{"id":"4583","messageId":"1117990178.10424.15.camel@port.evillabs.net","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506031450190.1876@ppc970.osdl.org","subject":"Re: [PATCH] git-daemon server","fromName":"Jason McMullan","fromEmail":"jason.mcmullan@timesys.com","sentAt":"2005-06-05T16:49:38Z","receivedAt":"2005-06-05T16:49:38Z","isPatch":true,"sender":{"key":"jason.mcmullan@timesys.com","avatar":null},"body":"On Fri, 2005-06-03 at 14:59 -0700, Linus Torvalds wrote:\n> Me, I want to have a fairly simple script that does the equivalent of what\n> I do now for pushing:\n> \n> \trsync -av --delete --exclude-from=.exclude .git/ master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n> \n> except I'd want it to do the locking and the \"only accept trivial pushes\" \n> stuff (ie no merging, just a pure update).\n\n\n$ GITCONNECTION=\"--tcp ....\"\n\n$ git-sync $GITCONNECTION head master master `cat .git/HEAD`\n\n(Yeah, the 'master master' is a cheezy way to do an update, but\n if you're the only one who can update the head, it's a non-issue)\n\n\n"},{"id":"4592","messageId":"Pine.LNX.4.58.0506051105510.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"1117990178.10424.15.camel@port.evillabs.net","subject":"Re: [PATCH] git-daemon server","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-05T18:11:21Z","receivedAt":"2005-06-05T18:11:21Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 5 Jun 2005, Jason McMullan wrote:\n>\n> On Fri, 2005-06-03 at 14:59 -0700, Linus Torvalds wrote:\n> > Me, I want to have a fairly simple script that does the equivalent of what\n> > I do now for pushing:\n> > \n> > \trsync -av --delete --exclude-from=.exclude .git/ master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n> > \n> > except I'd want it to do the locking and the \"only accept trivial pushes\" \n> > stuff (ie no merging, just a pure update).\n> \n> \n> $ GITCONNECTION=\"--tcp ....\"\n\nNope. I'm not going to run untrusted deamons of my own on master.\n\nI'm serious about the \"ssh or nothing\" thing. Anything but a direct ssh \nconection is simply not an option.\n\n\t\tLinus\n"},{"id":"4608","messageId":"Pine.LNX.4.58.0506051427280.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"7vfyvxb89m.fsf_-_@assigned-by-dhcp.cox.net","subject":"Re: [PATCH-CAREFUL/RENAME] rename git-rpush and git-rpull to git-ssh-push and git-ssh-pull","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-05T21:31:08Z","receivedAt":"2005-06-05T21:31:08Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 4 Jun 2005, Junio C Hamano wrote:\n>\n> *** Linus, please be careful with this patch.  This uses\n> *** extended git \"rename\" diff format, and I doubt that\n> *** traditional patch -p1 would do the right thing. \n\nIndeed.\n\nHowever, I've now made \"git-apply\" fully functional, and as far as I can \ntell, it would happily eat this patch. However, it so happens that your \npatch conflicts with the other patches sent yesterday, so it won't.\n\nOr maybe I screwed up. I applied your previous four patches with the new \nmagic git-apply thing, and it all _seems_ to work fine, but it might make \nsense if you double-checked it, and then we'll try this again and use it \nas the test-case for the new git-apply program.\n\nBtw, while talking about \"sensible\", I really think somebody should look\nmy \"apply.c\" file over. It seems simple enough, and it does seem to work,\nbut considering that I just totally replaced \"patch\" in my applicator\nscript with this new thing, if it gets something wrong...\n\n\t\tLinus\n"},{"id":"4615","messageId":"7vmzq4zata.fsf@assigned-by-dhcp.cox.net","threadId":"821","inReplyTo":"Pine.LNX.4.58.0506051427280.1876@ppc970.osdl.org","subject":"[PATCH-CAREFUL/RENAME] rename git-rpush and git-rpull to git-ssh-push and git-ssh-pull","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-05T22:41:05Z","receivedAt":"2005-06-05T22:41:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":">>>>> \"LT\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLT> However, I've now made \"git-apply\" fully functional, and as far as I can \nLT> tell, it would happily eat this patch. However, it so happens that your \nLT> patch conflicts with the other patches sent yesterday, so it won't.\n\nHere is a rebase.  To apply with git-apply, you need the \"Yes,\nsir\" patch to grok \"rename from/to\".\n\n------------\nIn preparation for 1.0 release, this makes the command names\nconsistent with others in git-*-pull family.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\ndiff --git a/Documentation/git-rpull.txt b/Documentation/git-ssh-pull.txt\nsimilarity index 90%\nrename from Documentation/git-rpull.txt\nrename to Documentation/git-ssh-pull.txt\n--- a/Documentation/git-rpull.txt\n+++ b/Documentation/git-ssh-pull.txt\n@@ -1,21 +1,21 @@\n-git-rpull(1)\n-============\n+git-ssh-pull(1)\n+===============\n v0.1, May 2005\n \n NAME\n ----\n-git-rpull - Pulls from a remote repository over ssh connection\n+git-ssh-pull - Pulls from a remote repository over ssh connection\n \n \n \n SYNOPSIS\n --------\n-'git-rpull' [-c] [-t] [-a] [-d] [-v] [--recover] commit-id url\n+'git-ssh-pull' [-c] [-t] [-a] [-d] [-v] [--recover] commit-id url\n \n DESCRIPTION\n -----------\n-Pulls from a remote repository over ssh connection, invoking git-rpush on\n-the other end.\n+Pulls from a remote repository over ssh connection, invoking git-ssh-push\n+on the other end.\n \n OPTIONS\n -------\ndiff --git a/Documentation/git-rpush.txt b/Documentation/git-ssh-push.txt\nsimilarity index 71%\nrename from Documentation/git-rpush.txt\nrename to Documentation/git-ssh-push.txt\n--- a/Documentation/git-rpush.txt\n+++ b/Documentation/git-ssh-push.txt\n@@ -1,19 +1,19 @@\n-git-rpush(1)\n-============\n+git-ssh-push(1)\n+===============\n v0.1, May 2005\n \n NAME\n ----\n-git-rpush - Helper \"server-side\" program used by git-rpull\n+git-ssh-push - Helper \"server-side\" program used by git-ssh-pull\n \n \n SYNOPSIS\n --------\n-'git-rpush'\n+'git-ssh-push'\n \n DESCRIPTION\n -----------\n-Helper \"server-side\" program used by git-rpull.\n+Helper \"server-side\" program used by git-ssh-pull.\n \n \n Author\ndiff --git a/Documentation/git.txt b/Documentation/git.txt\n--- a/Documentation/git.txt\n+++ b/Documentation/git.txt\n@@ -148,7 +148,7 @@ link:git-resolve-script.html[git-resolve\n link:git-tag-script.html[git-tag-script]::\n \tAn example script to create a tag object signed with GPG\n \n-link:git-rpull.html[git-rpull]::\n+link:git-ssh-pull.html[git-ssh-pull]::\n \tPulls from a remote repository over ssh connection\n \n Interogators:\n@@ -156,8 +156,8 @@ Interogators:\n link:git-diff-helper.html[git-diff-helper]::\n \tGenerates patch format output for git-diff-*\n \n-link:git-rpush.html[git-rpush]::\n-\tHelper \"server-side\" program used by git-rpull\n+link:git-ssh-push.html[git-ssh-push]::\n+\tHelper \"server-side\" program used by git-ssh-pull\n \n \n \ndiff --git a/Makefile b/Makefile\n--- a/Makefile\n+++ b/Makefile\n@@ -30,7 +30,7 @@ PROG=   git-update-cache git-diff-files \n \tgit-checkout-cache git-diff-tree git-rev-tree git-ls-files \\\n \tgit-check-files git-ls-tree git-merge-base git-merge-cache \\\n \tgit-unpack-file git-export git-diff-cache git-convert-cache \\\n-\tgit-http-pull git-rpush git-rpull git-rev-list git-mktag \\\n+\tgit-http-pull git-ssh-push git-ssh-pull git-rev-list git-mktag \\\n \tgit-diff-helper git-tar-tree git-local-pull git-write-blob \\\n \tgit-get-tar-commit-id git-mkdelta git-apply git-stripspace\n \n@@ -105,8 +105,8 @@ git-diff-cache: diff-cache.c\n git-convert-cache: convert-cache.c\n git-http-pull: http-pull.c pull.c\n git-local-pull: local-pull.c pull.c\n-git-rpush: rsh.c\n-git-rpull: rsh.c pull.c\n+git-ssh-push: rsh.c\n+git-ssh-pull: rsh.c pull.c\n git-rev-list: rev-list.c\n git-mktag: mktag.c\n git-diff-helper: diff-helper.c\ndiff --git a/rpull.c b/ssh-pull.c\nsimilarity index 97%\nrename from rpull.c\nrename to ssh-pull.c\n--- a/rpull.c\n+++ b/ssh-pull.c\n@@ -64,13 +64,13 @@ int main(int argc, char **argv)\n \t\targ++;\n \t}\n \tif (argc < arg + 2) {\n-\t\tusage(\"git-rpull [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url\");\n+\t\tusage(\"git-ssh-pull [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url\");\n \t\treturn 1;\n \t}\n \tcommit_id = argv[arg];\n \turl = argv[arg + 1];\n \n-\tif (setup_connection(&fd_in, &fd_out, \"git-rpush\", url, arg, argv + 1))\n+\tif (setup_connection(&fd_in, &fd_out, \"git-ssh-push\", url, arg, argv + 1))\n \t\treturn 1;\n \n \tif (get_version())\ndiff --git a/rpush.c b/ssh-push.c\nsimilarity index 93%\nrename from rpush.c\nrename to ssh-push.c\n--- a/rpush.c\n+++ b/ssh-push.c\n@@ -16,7 +16,7 @@ int serve_object(int fd_in, int fd_out) \n \tdo {\n \t\tsize = read(fd_in, sha1 + posn, 20 - posn);\n \t\tif (size < 0) {\n-\t\t\tperror(\"git-rpush: read \");\n+\t\t\tperror(\"git-ssh-push: read \");\n \t\t\treturn -1;\n \t\t}\n \t\tif (!size)\n@@ -30,7 +30,7 @@ int serve_object(int fd_in, int fd_out) \n \tbuf = map_sha1_file(sha1, &objsize);\n \t\n \tif (!buf) {\n-\t\tfprintf(stderr, \"git-rpush: could not find %s\\n\", \n+\t\tfprintf(stderr, \"git-ssh-push: could not find %s\\n\", \n \t\t\tsha1_to_hex(sha1));\n \t\tremote = -1;\n \t}\n@@ -45,9 +45,9 @@ int serve_object(int fd_in, int fd_out) \n \t\tsize = write(fd_out, buf + posn, objsize - posn);\n \t\tif (size <= 0) {\n \t\t\tif (!size) {\n-\t\t\t\tfprintf(stderr, \"git-rpush: write closed\");\n+\t\t\t\tfprintf(stderr, \"git-ssh-push: write closed\");\n \t\t\t} else {\n-\t\t\t\tperror(\"git-rpush: write \");\n+\t\t\t\tperror(\"git-ssh-push: write \");\n \t\t\t}\n \t\t\treturn -1;\n \t\t}\n@@ -71,7 +71,7 @@ void service(int fd_in, int fd_out) {\n \t\tretval = read(fd_in, &type, 1);\n \t\tif (retval < 1) {\n \t\t\tif (retval < 0)\n-\t\t\t\tperror(\"rpush: read \");\n+\t\t\t\tperror(\"git-ssh-push: read \");\n \t\t\treturn;\n \t\t}\n \t\tif (type == 'v' && serve_version(fd_in, fd_out))\n@@ -91,12 +91,12 @@ int main(int argc, char **argv)\n                 arg++;\n         }\n         if (argc < arg + 2) {\n-\t\tusage(\"git-rpush [-c] [-t] [-a] commit-id url\");\n+\t\tusage(\"git-ssh-push [-c] [-t] [-a] commit-id url\");\n                 return 1;\n         }\n \tcommit_id = argv[arg];\n \turl = argv[arg + 1];\n-\tif (setup_connection(&fd_in, &fd_out, \"git-rpull\", url, arg, argv + 1))\n+\tif (setup_connection(&fd_in, &fd_out, \"git-ssh-pull\", url, arg, argv + 1))\n \t\treturn 1;\n \n \tservice(fd_in, fd_out);\n\n"},{"id":"4616","messageId":"Pine.LNX.4.58.0506051613370.1876@ppc970.osdl.org","threadId":"821","inReplyTo":"7vmzq4zata.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH-CAREFUL/RENAME] rename git-rpush and git-rpull to git-ssh-push and git-ssh-pull","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-06-05T23:17:56Z","receivedAt":"2005-06-05T23:17:56Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 5 Jun 2005, Junio C Hamano wrote:\n> \n> Here is a rebase.  To apply with git-apply, you need the \"Yes,\n> sir\" patch to grok \"rename from/to\".\n\nSeems to have applied correctly. Very nice.\n\n\t\tLinus\n"}]}