X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=refs.c;h=67d2a502afb60050f0ce750c21ae1a42fa5cb803;hb=55029ae4dac07942437c0c715ea7c8ac60dd3576;hp=fc26a93cbadfe4795d06c99409f0b6e33aa22a20;hpb=79803322c1d8d2f74e1a53d44f363d878180e0f5;p=git.git diff --git a/refs.c b/refs.c index fc26a93cb..67d2a502a 100644 --- a/refs.c +++ b/refs.c @@ -613,32 +613,37 @@ int check_ref_format(const char *ref) while ((ch = *cp++) == '/') ; /* tolerate duplicated slashes */ if (!ch) - return -1; /* should not end with slashes */ + /* should not end with slashes */ + return CHECK_REF_FORMAT_ERROR; /* we are at the beginning of the path component */ if (ch == '.') - return -1; + return CHECK_REF_FORMAT_ERROR; bad_type = bad_ref_char(ch); if (bad_type) { - return (bad_type == 2 && !*cp) ? -3 : -1; + return (bad_type == 2 && !*cp) + ? CHECK_REF_FORMAT_WILDCARD + : CHECK_REF_FORMAT_ERROR; } /* scan the rest of the path component */ while ((ch = *cp++) != 0) { bad_type = bad_ref_char(ch); if (bad_type) { - return (bad_type == 2 && !*cp) ? -3 : -1; + return (bad_type == 2 && !*cp) + ? CHECK_REF_FORMAT_WILDCARD + : CHECK_REF_FORMAT_ERROR; } if (ch == '/') break; if (ch == '.' && *cp == '.') - return -1; + return CHECK_REF_FORMAT_ERROR; } level++; if (!ch) { if (level < 2) - return -2; /* at least of form "heads/blah" */ - return 0; + return CHECK_REF_FORMAT_ONELEVEL; + return CHECK_REF_FORMAT_OK; } } } @@ -653,6 +658,13 @@ const char *ref_rev_parse_rules[] = { NULL }; +const char *ref_fetch_rules[] = { + "%.*s", + "refs/%.*s", + "refs/heads/%.*s", + NULL +}; + int refname_match(const char *abbrev_name, const char *full_name, const char **rules) { const char **p; @@ -809,9 +821,13 @@ struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1) struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1, int flags) { - if (check_ref_format(ref) == -1) + switch (check_ref_format(ref)) { + default: return NULL; - return lock_ref_sha1_basic(ref, old_sha1, flags, NULL); + case 0: + case CHECK_REF_FORMAT_ONELEVEL: + return lock_ref_sha1_basic(ref, old_sha1, flags, NULL); + } } static struct lock_file packlock; @@ -848,7 +864,6 @@ static int repack_without_ref(const char *refname) die("too long a refname '%s'", list->name); write_or_die(fd, line, len); } - close(fd); return commit_lock_file(&packlock); } @@ -1003,14 +1018,27 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg) return 1; } +static int close_ref(struct ref_lock *lock) +{ + if (close_lock_file(lock->lk)) + return -1; + lock->lock_fd = -1; + return 0; +} + +static int commit_ref(struct ref_lock *lock) +{ + if (commit_lock_file(lock->lk)) + return -1; + lock->lock_fd = -1; + return 0; +} + void unlock_ref(struct ref_lock *lock) { - if (lock->lock_fd >= 0) { - close(lock->lock_fd); - /* Do not free lock->lk -- atexit() still looks at them */ - if (lock->lk) - rollback_lock_file(lock->lk); - } + /* Do not free lock->lk -- atexit() still looks at them */ + if (lock->lk) + rollback_lock_file(lock->lk); free(lock->ref_name); free(lock->orig_ref_name); free(lock); @@ -1087,7 +1115,7 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, adjust_shared_perm(log_file); msglen = msg ? strlen(msg) : 0; - committer = git_committer_info(-1); + committer = git_committer_info(0); maxlen = strlen(committer) + msglen + 100; logrec = xmalloc(maxlen); len = sprintf(logrec, "%s %s %s\n", @@ -1103,10 +1131,16 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, return 0; } +static int is_branch(const char *refname) +{ + return !strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/"); +} + int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *logmsg) { static char term = '\n'; + struct object *o; if (!lock) return -1; @@ -1114,9 +1148,22 @@ int write_ref_sha1(struct ref_lock *lock, unlock_ref(lock); return 0; } + o = parse_object(sha1); + if (!o) { + error("Trying to write ref %s with nonexistant object %s", + lock->ref_name, sha1_to_hex(sha1)); + unlock_ref(lock); + return -1; + } + if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) { + error("Trying to write non-commit object %s to branch %s", + sha1_to_hex(sha1), lock->ref_name); + unlock_ref(lock); + return -1; + } if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 || write_in_full(lock->lock_fd, &term, 1) != 1 - || close(lock->lock_fd) < 0) { + || close_ref(lock) < 0) { error("Couldn't write %s", lock->lk->filename); unlock_ref(lock); return -1; @@ -1149,12 +1196,11 @@ int write_ref_sha1(struct ref_lock *lock, !strcmp(head_ref, lock->ref_name)) log_ref_write("HEAD", lock->old_sha1, sha1, logmsg); } - if (commit_lock_file(lock->lk)) { + if (commit_ref(lock)) { error("Couldn't set %s", lock->ref_name); unlock_ref(lock); return -1; } - lock->lock_fd = -1; unlock_ref(lock); return 0; } @@ -1457,3 +1503,11 @@ int update_ref(const char *action, const char *refname, } return 0; } + +struct ref *find_ref_by_name(struct ref *list, const char *name) +{ + for ( ; list; list = list->next) + if (!strcmp(list->name, name)) + return list; + return NULL; +}