#include "cache.h"
#include "tag.h"
#include "commit.h"
+#include "pkt-line.h"
+#include "utf8.h"
int save_commit_buffer = 1;
return;
graft_file = get_graft_file();
read_graft_file(graft_file);
+ /* make sure shallows are read */
+ is_repository_shallow();
commit_graft_prepared = 1;
}
return commit_graft[pos];
}
+int write_shallow_commits(int fd, int use_pack_protocol)
+{
+ int i, count = 0;
+ for (i = 0; i < commit_graft_nr; i++)
+ if (commit_graft[i]->nr_parent < 0) {
+ const char *hex =
+ sha1_to_hex(commit_graft[i]->sha1);
+ count++;
+ if (use_pack_protocol)
+ packet_write(fd, "shallow %s", hex);
+ else {
+ write(fd, hex, 40);
+ write(fd, "\n", 1);
+ }
+ }
+ return count;
+}
+
+int unregister_shallow(const unsigned char *sha1)
+{
+ int pos = commit_graft_pos(sha1);
+ if (pos < 0)
+ return -1;
+ if (pos + 1 < commit_graft_nr)
+ memcpy(commit_graft + pos, commit_graft + pos + 1,
+ sizeof(struct commit_graft *)
+ * (commit_graft_nr - pos - 1));
+ commit_graft_nr--;
+ return 0;
+}
+
int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
{
char *tail = buffer;
return offset;
}
-unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
- unsigned long len, char *buf, unsigned long space,
+static char *get_header(const struct commit *commit, const char *key)
+{
+ int key_len = strlen(key);
+ const char *line = commit->buffer;
+
+ for (;;) {
+ const char *eol = strchr(line, '\n'), *next;
+
+ if (line == eol)
+ return NULL;
+ if (!eol) {
+ eol = line + strlen(line);
+ next = NULL;
+ } else
+ next = eol + 1;
+ if (!strncmp(line, key, key_len) && line[key_len] == ' ') {
+ int len = eol - line - key_len;
+ char *ret = xmalloc(len);
+ memcpy(ret, line + key_len + 1, len - 1);
+ ret[len - 1] = '\0';
+ return ret;
+ }
+ line = next;
+ }
+}
+
+static char *replace_encoding_header(char *buf, char *encoding)
+{
+ char *encoding_header = strstr(buf, "\nencoding ");
+ char *end_of_encoding_header;
+ int encoding_header_pos;
+ int encoding_header_len;
+ int new_len;
+ int need_len;
+ int buflen = strlen(buf) + 1;
+
+ if (!encoding_header)
+ return buf; /* should not happen but be defensive */
+ encoding_header++;
+ end_of_encoding_header = strchr(encoding_header, '\n');
+ if (!end_of_encoding_header)
+ return buf; /* should not happen but be defensive */
+ end_of_encoding_header++;
+
+ encoding_header_len = end_of_encoding_header - encoding_header;
+ encoding_header_pos = encoding_header - buf;
+
+ if (is_encoding_utf8(encoding)) {
+ /* we have re-coded to UTF-8; drop the header */
+ memmove(encoding_header, end_of_encoding_header,
+ buflen - (encoding_header_pos + encoding_header_len));
+ return buf;
+ }
+ new_len = strlen(encoding);
+ need_len = new_len + strlen("encoding \n");
+ if (encoding_header_len < need_len) {
+ buf = xrealloc(buf, buflen + (need_len - encoding_header_len));
+ encoding_header = buf + encoding_header_pos;
+ end_of_encoding_header = encoding_header + encoding_header_len;
+ }
+ memmove(end_of_encoding_header + (need_len - encoding_header_len),
+ end_of_encoding_header,
+ buflen - (encoding_header_pos + encoding_header_len));
+ memcpy(encoding_header + 9, encoding, strlen(encoding));
+ encoding_header[9 + new_len] = '\n';
+ return buf;
+}
+
+static char *logmsg_reencode(const struct commit *commit)
+{
+ char *encoding;
+ char *out;
+ char *output_encoding = (git_log_output_encoding
+ ? git_log_output_encoding
+ : git_commit_encoding);
+
+ if (!output_encoding)
+ output_encoding = "utf-8";
+ else if (!*output_encoding)
+ return NULL;
+ encoding = get_header(commit, "encoding");
+ if (!encoding)
+ return NULL;
+ if (!strcmp(encoding, output_encoding))
+ out = strdup(commit->buffer);
+ else
+ out = reencode_string(commit->buffer,
+ output_encoding, encoding);
+ if (out)
+ out = replace_encoding_header(out, output_encoding);
+
+ free(encoding);
+ if (!out)
+ return NULL;
+ return out;
+}
+
+unsigned long pretty_print_commit(enum cmit_fmt fmt,
+ const struct commit *commit,
+ unsigned long len,
+ char *buf, unsigned long space,
int abbrev, const char *subject,
- const char *after_subject, int relative_date)
+ const char *after_subject,
+ int relative_date)
{
- int hdr = 1, body = 0;
+ int hdr = 1, body = 0, seen_title = 0;
unsigned long offset = 0;
int indent = 4;
int parents_shown = 0;
const char *msg = commit->buffer;
int plain_non_ascii = 0;
+ char *reencoded = logmsg_reencode(commit);
+
+ if (reencoded)
+ msg = reencoded;
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
indent = 0;
for (in_body = i = 0; (ch = msg[i]) && i < len; i++) {
if (!in_body) {
/* author could be non 7-bit ASCII but
- * the log may so; skip over the
+ * the log may be so; skip over the
* header part first.
*/
if (ch == '\n' &&
body = 1;
if (is_empty_line(line, &linelen)) {
+ if (!seen_title)
+ continue;
if (!body)
continue;
if (subject)
break;
}
+ seen_title = 1;
if (subject) {
int slen = strlen(subject);
memcpy(buf + offset, subject, slen);
if (fmt == CMIT_FMT_EMAIL && !body)
buf[offset++] = '\n';
buf[offset] = '\0';
+
+ free(reencoded);
return offset;
}
free(rslt);
return result;
}
+
+int in_merge_bases(struct commit *rev1, struct commit *rev2)
+{
+ struct commit_list *bases, *b;
+ int ret = 0;
+
+ bases = get_merge_bases(rev1, rev2, 1);
+ for (b = bases; b; b = b->next) {
+ if (!hashcmp(rev1->object.sha1, b->item->object.sha1)) {
+ ret = 1;
+ break;
+ }
+ }
+
+ free_commit_list(bases);
+ return ret;
+}