From: Junio C Hamano Date: Wed, 29 Aug 2012 21:50:07 +0000 (-0700) Subject: Merge branch 'jc/capabilities' X-Git-Tag: v1.8.0-rc0~121 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/97349a2a74fdd42afd5a1f8e8e92cddf47f28193?ds=inline;hp=-c Merge branch 'jc/capabilities' Some capabilities were asked by fetch-pack even when upload-pack did not advertise that they are available. Fix fetch-pack not to do so. * jc/capabilities: fetch-pack: mention server version with verbose output parse_feature_request: make it easier to see feature values fetch-pack: do not ask for unadvertised capabilities do not send client agent unless server does first send-pack: fix capability-sending logic include agent identifier in capability string --- 97349a2a74fdd42afd5a1f8e8e92cddf47f28193 diff --combined builtin/receive-pack.c index 3f05d971ec,fbfa1289c1..2cb854feb4 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@@ -12,6 -12,7 +12,7 @@@ #include "string-list.h" #include "sha1-array.h" #include "connected.h" + #include "version.h" static const char receive_pack_usage[] = "git receive-pack "; @@@ -121,10 -122,11 +122,11 @@@ static void show_ref(const char *path, if (sent_capabilities) packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); else - packet_write(1, "%s %s%c%s%s\n", + packet_write(1, "%s %s%c%s%s agent=%s\n", sha1_to_hex(sha1), path, 0, " report-status delete-refs side-band-64k quiet", - prefer_ofs_delta ? " ofs-delta" : ""); + prefer_ofs_delta ? " ofs-delta" : "", + git_user_agent_sanitized()); sent_capabilities = 1; } @@@ -977,8 -979,7 +979,8 @@@ int cmd_receive_pack(int argc, const ch const char *argv_gc_auto[] = { "gc", "--auto", "--quiet", NULL, }; - run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); + int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR; + run_command_v_opt(argv_gc_auto, opt); } if (auto_update_server_info) update_server_info(0); diff --combined cache.h index 67f28b4da9,b71b0650f4..95daa690aa --- a/cache.h +++ b/cache.h @@@ -128,13 -128,13 +128,13 @@@ struct cache_entry unsigned int ce_gid; unsigned int ce_size; unsigned int ce_flags; + unsigned int ce_namelen; unsigned char sha1[20]; struct cache_entry *next; struct cache_entry *dir_next; char name[FLEX_ARRAY]; /* more */ }; -#define CE_NAMEMASK (0x0fff) #define CE_STAGEMASK (0x3000) #define CE_EXTENDED (0x4000) #define CE_VALID (0x8000) @@@ -198,12 -198,21 +198,12 @@@ static inline void copy_cache_entry(str dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state; } -static inline unsigned create_ce_flags(size_t len, unsigned stage) +static inline unsigned create_ce_flags(unsigned stage) { - if (len >= CE_NAMEMASK) - len = CE_NAMEMASK; - return (len | (stage << CE_STAGESHIFT)); -} - -static inline size_t ce_namelen(const struct cache_entry *ce) -{ - size_t len = ce->ce_flags & CE_NAMEMASK; - if (len < CE_NAMEMASK) - return len; - return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK; + return (stage << CE_STAGESHIFT); } +#define ce_namelen(ce) ((ce)->ce_namelen) #define ce_size(ce) cache_entry_size(ce_namelen(ce)) #define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT) #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) @@@ -400,11 -409,8 +400,11 @@@ extern const char *setup_git_directory( extern char *prefix_path(const char *prefix, int len, const char *path); extern const char *prefix_filename(const char *prefix, int len, const char *path); extern int check_filename(const char *prefix, const char *name); -extern void verify_filename(const char *prefix, const char *name); +extern void verify_filename(const char *prefix, + const char *name, + int diagnose_misspelt_rev); extern void verify_non_filename(const char *prefix, const char *name); +extern int path_inside_repo(const char *prefix, const char *path); #define INIT_DB_QUIET 0x0001 @@@ -442,7 -448,6 +442,7 @@@ extern int discard_index(struct index_s extern int unmerged_index(const struct index_state *); extern int verify_path(const char *path); extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase); +extern int index_name_stage_pos(const struct index_state *, const char *name, int namelen, int stage); extern int index_name_pos(const struct index_state *, const char *name, int namelen); #define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */ #define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */ @@@ -555,7 -560,6 +555,7 @@@ extern int read_replace_refs extern int fsync_object_files; extern int core_preload_index; extern int core_apply_sparse_checkout; +extern int precomposed_unicode; enum branch_track { BRANCH_TRACK_UNSPECIFIED = -1, @@@ -615,8 -619,6 +615,8 @@@ extern char *git_snpath(char *buf, size __attribute__((format (printf, 3, 4))); extern char *git_pathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +extern char *mkpathdup(const char *fmt, ...) + __attribute__((format (printf, 1, 2))); /* Return a statically allocated filename matching the sha1 signature */ extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@@ -706,7 -708,6 +706,7 @@@ int set_shared_perm(const char *path, i int safe_create_leading_directories(char *path); int safe_create_leading_directories_const(const char *path); int mkdir_in_gitdir(const char *path); +extern void home_config_paths(char **global, char **xdg, char *file); extern char *expand_user_path(const char *path); const char *enter_repo(const char *path, int strict); static inline int is_absolute_path(const char *path) @@@ -782,25 -783,17 +782,25 @@@ struct object_context unsigned mode; }; +#define GET_SHA1_QUIETLY 01 +#define GET_SHA1_COMMIT 02 +#define GET_SHA1_COMMITTISH 04 +#define GET_SHA1_TREE 010 +#define GET_SHA1_TREEISH 020 +#define GET_SHA1_BLOB 040 +#define GET_SHA1_ONLY_TO_DIE 04000 + extern int get_sha1(const char *str, unsigned char *sha1); -extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int only_to_die, const char *prefix); -static inline int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode) -{ - return get_sha1_with_mode_1(str, sha1, mode, 0, NULL); -} -extern int get_sha1_with_context_1(const char *name, unsigned char *sha1, struct object_context *orc, int only_to_die, const char *prefix); -static inline int get_sha1_with_context(const char *str, unsigned char *sha1, struct object_context *orc) -{ - return get_sha1_with_context_1(str, sha1, orc, 0, NULL); -} +extern int get_sha1_commit(const char *str, unsigned char *sha1); +extern int get_sha1_committish(const char *str, unsigned char *sha1); +extern int get_sha1_tree(const char *str, unsigned char *sha1); +extern int get_sha1_treeish(const char *str, unsigned char *sha1); +extern int get_sha1_blob(const char *str, unsigned char *sha1); +extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix); +extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc); + +typedef int each_abbrev_fn(const unsigned char *sha1, void *); +extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *); /* * Try to read a SHA1 in hexadecimal format from the 40 characters @@@ -864,7 -857,6 +864,7 @@@ extern int validate_headref(const char extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int df_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2); +extern int cache_name_stage_compare(const char *name1, int len1, int stage1, const char *name2, int len2, int stage2); extern void *read_object_with_reference(const unsigned char *sha1, const char *required_type, @@@ -1038,7 -1030,9 +1038,9 @@@ struct extra_have_objects }; extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *); extern int server_supports(const char *feature); - extern const char *parse_feature_request(const char *features, const char *feature); + extern int parse_feature_request(const char *features, const char *feature); + extern const char *server_feature_value(const char *feature, int *len_ret); + extern const char *parse_feature_value(const char *feature_list, const char *feature, int *len_ret); extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path); diff --combined connect.c index 55a85adea9,9aec10cec1..49e56ba35a --- a/connect.c +++ b/connect.c @@@ -49,16 -49,6 +49,16 @@@ static void add_extra_have(struct extra extra->nr++; } +static void die_initial_contact(int got_at_least_one_head) +{ + if (got_at_least_one_head) + die("The remote end hung up upon initial contact"); + else + die("Could not read from remote repository.\n\n" + "Please make sure you have the correct access rights\n" + "and the repository exists."); +} + /* * Read all the refs from the other end */ @@@ -66,8 -56,6 +66,8 @@@ struct ref **get_remote_heads(int in, s unsigned int flags, struct extra_have_objects *extra_have) { + int got_at_least_one_head = 0; + *list = NULL; for (;;) { struct ref *ref; @@@ -76,10 -64,7 +76,10 @@@ char *name; int len, name_len; - len = packet_read_line(in, buffer, sizeof(buffer)); + len = packet_read(in, buffer, sizeof(buffer)); + if (len < 0) + die_initial_contact(got_at_least_one_head); + if (!len) break; if (buffer[len-1] == '\n') @@@ -110,17 -95,11 +110,12 @@@ hashcpy(ref->old_sha1, old_sha1); *list = ref; list = &ref->next; + got_at_least_one_head = 1; } return list; } - int server_supports(const char *feature) - { - return !!parse_feature_request(server_capabilities, feature); - } - - const char *parse_feature_request(const char *feature_list, const char *feature) + const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp) { int len; @@@ -132,14 -111,46 +127,46 @@@ const char *found = strstr(feature_list, feature); if (!found) return NULL; - if ((feature_list == found || isspace(found[-1])) && - (!found[len] || isspace(found[len]) || found[len] == '=')) - return found; + if (feature_list == found || isspace(found[-1])) { + const char *value = found + len; + /* feature with no value (e.g., "thin-pack") */ + if (!*value || isspace(*value)) { + if (lenp) + *lenp = 0; + return value; + } + /* feature with a value (e.g., "agent=git/1.2.3") */ + else if (*value == '=') { + value++; + if (lenp) + *lenp = strcspn(value, " \t\n"); + return value; + } + /* + * otherwise we matched a substring of another feature; + * keep looking + */ + } feature_list = found + 1; } return NULL; } + int parse_feature_request(const char *feature_list, const char *feature) + { + return !!parse_feature_value(feature_list, feature, NULL); + } + + const char *server_feature_value(const char *feature, int *len) + { + return parse_feature_value(server_capabilities, feature, len); + } + + int server_supports(const char *feature) + { + return !!server_feature_value(feature, NULL); + } + enum protocol { PROTO_LOCAL = 1, PROTO_SSH, @@@ -552,7 -563,7 +579,7 @@@ struct child_process *git_connect(int f * Add support for ssh port: ssh://host.xy:/... */ if (protocol == PROTO_SSH && host != url) - port = get_port(host); + port = get_port(end); if (protocol == PROTO_GIT) { /* These underlying connection commands die() if they