static void adjust_git_path(struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; if (git_graft_env && is_dir_file(base, "info", "grafts")) strbuf_splice(buf, 0, buf->len, get_graft_file(), strlen(get_graft_file())); else if (git_index_env && !strcmp(base, "index")) strbuf_splice(buf, 0, buf->len, get_index_file(), strlen(get_index_file())); else if (git_db_env && dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, get_object_directory()); else if (git_common_dir_env) update_common_dir(buf, git_dir_len); }
static char *replace_encoding_header(char *buf, const char *encoding) { struct strbuf tmp = STRBUF_INIT; size_t start, len; char *cp = buf; /* guess if there is an encoding header before a \n\n */ while (strncmp(cp, "encoding ", strlen("encoding "))) { cp = strchr(cp, '\n'); if (!cp || *++cp == '\n') return buf; } start = cp - buf; cp = strchr(cp, '\n'); if (!cp) return buf; /* should not happen but be defensive */ len = cp + 1 - (buf + start); strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1); if (is_encoding_utf8(encoding)) { /* we have re-coded to UTF-8; drop the header */ strbuf_remove(&tmp, start, len); } else { /* just replaces XXXX in 'encoding XXXX\n' */ strbuf_splice(&tmp, start + strlen("encoding "), len - strlen("encoding \n"), encoding, strlen(encoding)); } return strbuf_detach(&tmp, NULL); }
static void adjust_git_path(const struct repository *repo, struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; if (is_dir_file(base, "info", "grafts")) strbuf_splice(buf, 0, buf->len, repo->graft_file, strlen(repo->graft_file)); else if (!strcmp(base, "index")) strbuf_splice(buf, 0, buf->len, repo->index_file, strlen(repo->index_file)); else if (dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, repo->objects->odb->path); else if (git_hooks_path && dir_prefix(base, "hooks")) replace_dir(buf, git_dir_len + 5, git_hooks_path); else if (repo->different_commondir) update_common_dir(buf, git_dir_len, repo->commondir); }
static void setup_branch_path(struct branch_info *branch) { struct strbuf buf = STRBUF_INIT; strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL); if (strcmp(buf.buf, branch->name)) branch->name = xstrdup(buf.buf); strbuf_splice(&buf, 0, 0, "refs/heads/", 11); branch->path = strbuf_detach(&buf, NULL); }
static void replace_dir(struct strbuf *buf, int len, const char *newdir) { int newlen = strlen(newdir); int need_sep = (buf->buf[len] && !is_dir_sep(buf->buf[len])) && !is_dir_sep(newdir[newlen - 1]); if (need_sep) len--; /* keep one char, to be replaced with '/' */ strbuf_splice(buf, 0, len, newdir, newlen); if (need_sep) buf->buf[newlen] = '/'; }
// returns 0 until it's past the end of the string // only works on unix newlines ('\n' only) static int get_strbuf_line(struct strbuf* str, int* pos, struct strbuf* line) { int begin; int len; char* buf; len = str->len; if (*pos >= len) { return 1; } begin = *pos; buf = str->buf; while (*pos < len && (buf[*pos] != '\r' && buf[*pos] != '\n')) { (*pos)++; } strbuf_splice(line, 0, line->len, str->buf+begin, (*pos)-begin); if (buf[*pos] == '\r' && *pos < (len-1) && buf[(*pos)+1] == '\n') { (*pos) += 2; } else { (*pos)++; } return 0; }
static int replace_parents(struct strbuf *buf, int argc, const char **argv) { struct strbuf new_parents = STRBUF_INIT; const char *parent_start, *parent_end; int i; /* find existing parents */ parent_start = buf->buf; parent_start += GIT_SHA1_HEXSZ + 6; /* "tree " + "hex sha1" + "\n" */ parent_end = parent_start; while (starts_with(parent_end, "parent ")) parent_end += 48; /* "parent " + "hex sha1" + "\n" */ /* prepare new parents */ for (i = 0; i < argc; i++) { struct object_id oid; if (get_oid(argv[i], &oid) < 0) { strbuf_release(&new_parents); return error(_("Not a valid object name: '%s'"), argv[i]); } if (!lookup_commit_reference(&oid)) { strbuf_release(&new_parents); return error(_("could not parse %s"), argv[i]); } strbuf_addf(&new_parents, "parent %s\n", oid_to_hex(&oid)); } /* replace existing parents with new ones */ strbuf_splice(buf, parent_start - buf->buf, parent_end - parent_start, new_parents.buf, new_parents.len); strbuf_release(&new_parents); return 0; }
void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) { strbuf_splice(sb, pos, len, NULL, 0); }
void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) { strbuf_splice(sb, pos, 0, data, len); }
static inline void strbuf_replace(struct strbuf *sb, const char *a, const char *b) { const char *ptr = strstr(sb->buf, a); if (ptr) strbuf_splice(sb, ptr - sb->buf, strlen(a), b, strlen(b)); }
void append_signoff(struct strbuf *msgbuf, int ignore_footer, unsigned flag) { unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP; struct strbuf sob = STRBUF_INIT; int has_footer; strbuf_addstr(&sob, sign_off_header); strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"), getenv("GIT_COMMITTER_EMAIL"))); strbuf_addch(&sob, '\n'); /* * If the whole message buffer is equal to the sob, pretend that we * found a conforming footer with a matching sob */ if (msgbuf->len - ignore_footer == sob.len && !strncmp(msgbuf->buf, sob.buf, sob.len)) has_footer = 3; else has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer); if (!has_footer) { const char *append_newlines = NULL; size_t len = msgbuf->len - ignore_footer; if (!len) { /* * The buffer is completely empty. Leave foom for * the title and body to be filled in by the user. */ append_newlines = "\n\n"; } else if (msgbuf->buf[len - 1] != '\n') { /* * Incomplete line. Complete the line and add a * blank one so that there is an empty line between * the message body and the sob. */ append_newlines = "\n\n"; } else if (len == 1) { /* * Buffer contains a single newline. Add another * so that we leave room for the title and body. */ append_newlines = "\n"; } else if (msgbuf->buf[len - 2] != '\n') { /* * Buffer ends with a single newline. Add another * so that there is an empty line between the message * body and the sob. */ append_newlines = "\n"; } /* else, the buffer already ends with two newlines. */ if (append_newlines) strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0, append_newlines, strlen(append_newlines)); } if (has_footer != 3 && (!no_dup_sob || has_footer != 2)) strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0, sob.buf, sob.len); strbuf_release(&sob); }
void create_branch(const char *head, const char *name, const char *start_name, int force, int reflog, enum branch_track track) { struct ref_lock *lock; struct commit *commit; unsigned char sha1[20]; char *real_ref, msg[PATH_MAX + 20]; struct strbuf ref = STRBUF_INIT; int forcing = 0; int len; len = strlen(name); if (interpret_nth_last_branch(name, &ref) != len) { strbuf_reset(&ref); strbuf_add(&ref, name, len); } strbuf_splice(&ref, 0, 0, "refs/heads/", 11); if (check_ref_format(ref.buf)) die("'%s' is not a valid branch name.", name); if (resolve_ref(ref.buf, sha1, 1, NULL)) { if (!force) die("A branch named '%s' already exists.", name); else if (!is_bare_repository() && !strcmp(head, name)) die("Cannot force update the current branch."); forcing = 1; } real_ref = NULL; if (get_sha1(start_name, sha1)) die("Not a valid object name: '%s'.", start_name); switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) { case 0: /* Not branching from any existing branch */ if (track == BRANCH_TRACK_EXPLICIT) die("Cannot setup tracking information; starting point is not a branch."); break; case 1: /* Unique completion -- good, only if it is a real ref */ if (track == BRANCH_TRACK_EXPLICIT && !strcmp(real_ref, "HEAD")) die("Cannot setup tracking information; starting point is not a branch."); break; default: die("Ambiguous object name: '%s'.", start_name); break; } if ((commit = lookup_commit_reference(sha1)) == NULL) die("Not a valid branch point: '%s'.", start_name); hashcpy(sha1, commit->object.sha1); lock = lock_any_ref_for_update(ref.buf, NULL, 0); if (!lock) die("Failed to lock ref for update: %s.", strerror(errno)); if (reflog) log_all_ref_updates = 1; if (forcing) snprintf(msg, sizeof msg, "branch: Reset from %s", start_name); else snprintf(msg, sizeof msg, "branch: Created from %s", start_name); if (real_ref && track) setup_tracking(name, real_ref, track); if (write_ref_sha1(lock, sha1, msg) < 0) die("Failed to write ref: %s.", strerror(errno)); strbuf_release(&ref); free(real_ref); }