Merge branch 'js/reflog' into next

* js/reflog:
  Sanitize for_each_reflog_ent()
  merge-base: do not leak commit list
  Auto-quote config values in config.c:store_write_pair()
  Ignore git-init and git-remote
  rm git-rerere.perl -- it is now a built-in.
  cvsserver: fix revision number during file adds
  cvsserver: detect early of we are up to date and avoid costly rev-list
  Documentation: add git-remote man page
  short i/o: fix config updates to use write_in_full
  short i/o: fix calls to write to use xwrite or write_in_full
  short i/o: fix calls to read to use xread or read_in_full
  short i/o: clean up the naming for the write_{in,or}_xxx family
  --prune is now default for 'pack-refs'
  --utf8 is now default for 'git-am'
  git-commit: do not fail to print the diffstat even if there is a file named HEAD
  ssh-upload: prevent buffer overrun
This commit is contained in:
Junio C Hamano
2007-01-09 03:04:14 -08:00
45 changed files with 456 additions and 514 deletions

2
.gitignore vendored
View File

@@ -50,6 +50,7 @@ git-http-fetch
git-http-push
git-imap-send
git-index-pack
git-init
git-init-db
git-instaweb
git-local-fetch
@@ -92,6 +93,7 @@ git-rebase
git-receive-pack
git-reflog
git-relink
git-remote
git-repack
git-repo-config
git-request-pull

View File

@@ -9,7 +9,7 @@ git-am - Apply a series of patches in a mailbox
SYNOPSIS
--------
[verse]
'git-am' [--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way]
'git-am' [--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]
[--interactive] [--whitespace=<option>] <mbox>...
'git-am' [--skip | --resolved]
@@ -29,8 +29,21 @@ OPTIONS
Instead of `.dotest` directory, use <dir> as a working
area to store extracted patches.
--utf8, --keep::
Pass `-u` and `-k` flags to `git-mailinfo` (see
--keep::
Pass `-k` flag to `git-mailinfo` (see gitlink:git-mailinfo[1]).
--utf8::
Pass `-u` flag to `git-mailinfo` (see gitlink:git-mailinfo[1]).
The proposed commit log message taken from the e-mail
are re-coded into UTF-8 encoding (configuration variable
`i18n.commitencoding` can be used to specify project's
preferred encoding if it is not UTF-8).
+
This was optional in prior versions of git, but now it is the
default. You could use `--no-utf8` to override this.
--no-utf8::
Do not pass `-u` flag to `git-mailinfo` (see
gitlink:git-mailinfo[1]).
--binary::

View File

@@ -7,7 +7,7 @@ git-pack-refs - Pack heads and tags for efficient repository access
SYNOPSIS
--------
'git-pack-refs' [--all] [--prune]
'git-pack-refs' [--all] [--no-prune]
DESCRIPTION
-----------
@@ -40,10 +40,11 @@ developed and packing their tips does not help performance.
This option causes branch tips to be packed as well. Useful for
a repository with many branches of historical interests.
\--prune::
\--no-prune::
The command usually removes loose refs under `$GIT_DIR/refs`
hierarchy after packing them. This option tells it not to.
After packing the refs, remove loose refs under `$GIT_DIR/refs`
hierarchy. This should probably become default.
Author
------

View File

@@ -0,0 +1,76 @@
git-remote(1)
============
NAME
----
git-remote - manage set of tracked repositories
SYNOPSIS
--------
[verse]
'git-remote'
'git-remote' add <name> <url>
'git-remote' show <name>
DESCRIPTION
-----------
Manage the set of repositories ("remotes") whose branches you track.
With no arguments, shows a list of existing remotes.
In the second form, adds a remote named <name> for the repository at
<url>. The command `git fetch <name>` can then be used to create and
update remote-tracking branches <name>/<branch>.
In the third form, gives some information about the remote <name>.
The remote configuration is achieved using the `remote.origin.url` and
`remote.origin.fetch` configuration variables. (See
gitlink:git-repo-config[1]).
Examples
--------
Add a new remote, fetch, and check out a branch from it:
------------
$ git remote
origin
$ git branch -r
origin/master
$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git
$ git remote
linux-nfs
origin
$ git fetch
* refs/remotes/linux-nfs/master: storing branch 'master' ...
commit: bf81b46
$ git branch -r
origin/master
linux-nfs/master
$ git checkout -b nfs linux-nfs/master
...
------------
See Also
--------
gitlink:git-fetch[1]
gitlink:git-branch[1]
gitlink:git-repo-config[1]
Author
------
Written by Junio Hamano
Documentation
--------------
Documentation by J. Bruce Fields and the git-list <git@vger.kernel.org>.
GIT
---
Part of the gitlink:git[7] suite

View File

@@ -136,7 +136,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
if (i < 0)
goto err_ret;
data = xmalloc(st.st_size + 1);
if (st.st_size != xread(i, data, st.st_size)) {
if (st.st_size != read_in_full(i, data, st.st_size)) {
error("'%s': short read %s", filename, strerror(errno));
close(i);
free(data);

View File

@@ -4,7 +4,7 @@
#include "tag.h"
static const char builtin_pack_refs_usage[] =
"git-pack-refs [--all] [--prune]";
"git-pack-refs [--all] [--prune | --no-prune]";
struct ref_to_prune {
struct ref_to_prune *next;
@@ -90,10 +90,15 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
memset(&cbdata, 0, sizeof(cbdata));
cbdata.prune = 1;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--prune")) {
cbdata.prune = 1;
cbdata.prune = 1; /* now the default */
continue;
}
if (!strcmp(arg, "--no-prune")) {
cbdata.prune = 0;
continue;
}
if (!strcmp(arg, "--all")) {

View File

@@ -195,19 +195,12 @@ static int keep_entry(struct commit **it, unsigned char *sha1)
}
static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
char *data, void *cb_data)
const char *email, unsigned long timestamp, int tz,
const char *message, void *cb_data)
{
struct expire_reflog_cb *cb = cb_data;
unsigned long timestamp;
char *cp, *ep;
struct commit *old, *new;
cp = strchr(data, '>');
if (!cp || *++cp != ' ')
goto prune;
timestamp = strtoul(cp, &ep, 10);
if (*ep != ' ')
goto prune;
if (timestamp < cb->cmd->expire_total)
goto prune;
@@ -221,15 +214,20 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
(new && !in_merge_bases(new, cb->ref_commit))))
goto prune;
if (cb->newlog)
fprintf(cb->newlog, "%s %s %s",
sha1_to_hex(osha1), sha1_to_hex(nsha1), data);
if (cb->newlog) {
char sign = (tz < 0) ? '-' : '+';
int zone = (tz < 0) ? (-tz) : tz;
fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s",
sha1_to_hex(osha1), sha1_to_hex(nsha1),
email, timestamp, sign, zone,
message);
}
if (cb->cmd->verbose)
printf("keep %s", data);
printf("keep %s", message);
return 0;
prune:
if (!cb->newlog || cb->cmd->verbose)
printf("%sprune %s", cb->newlog ? "" : "would ", data);
printf("%sprune %s", cb->newlog ? "" : "would ", message);
return 0;
}

View File

@@ -51,9 +51,11 @@ static int write_rr(struct path_list *rr, int out_fd)
int i;
for (i = 0; i < rr->nr; i++) {
const char *path = rr->items[i].path;
write(out_fd, rr->items[i].util, 40);
write(out_fd, "\t", 1);
write(out_fd, path, strlen(path) + 1);
int length = strlen(path) + 1;
if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
write_in_full(out_fd, "\t", 1) != 1 ||
write_in_full(out_fd, path, length) != length)
die("unable to write rerere record");
}
close(out_fd);
return commit_lock_file(&write_lock);
@@ -244,7 +246,8 @@ static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
{
int i;
for (i = 0; i < nbuf; i++)
write(1, ptr[i].ptr, ptr[i].size);
if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
return -1;
return 0;
}

View File

@@ -74,7 +74,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
char *content = buffer + RECORDSIZE;
ssize_t n;
n = xread(0, buffer, HEADERSIZE);
n = read_in_full(0, buffer, HEADERSIZE);
if (n < HEADERSIZE)
die("git-get-tar-commit-id: read error");
if (header->typeflag[0] != 'g')
@@ -82,7 +82,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
if (memcmp(content, "52 comment=", 11))
return 1;
n = xwrite(1, content + 11, 41);
n = write_in_full(1, content + 11, 41);
if (n < 41)
die("git-get-tar-commit-id: write error");

View File

@@ -91,7 +91,7 @@ static void process_input(int child_fd, int band)
char buf[16384];
ssize_t sz = read(child_fd, buf, sizeof(buf));
if (sz < 0) {
if (errno != EINTR)
if (errno != EAGAIN && errno != EINTR)
error_clnt("read error: %s\n", strerror(errno));
return;
}

View File

@@ -433,10 +433,12 @@ extern char *git_commit_encoding;
extern char *git_log_output_encoding;
extern int copy_fd(int ifd, int ofd);
extern int read_in_full(int fd, void *buf, size_t count);
extern void read_or_die(int fd, void *buf, size_t count);
extern int write_in_full(int fd, const void *buf, size_t count, const char *);
extern int write_in_full(int fd, const void *buf, size_t count);
extern void write_or_die(int fd, const void *buf, size_t count);
extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
/* pager.c */
extern void setup_pager(void);

View File

@@ -249,8 +249,10 @@ int write_shallow_commits(int fd, int use_pack_protocol)
if (use_pack_protocol)
packet_write(fd, "shallow %s", hex);
else {
write(fd, hex, 40);
write(fd, "\n", 1);
if (write_in_full(fd, hex, 40) != 40)
break;
if (write_in_full(fd, "\n", 1) != 1)
break;
}
}
return count;
@@ -1010,7 +1012,7 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
free(nodes);
}
/* merge-rebase stuff */
/* merge-base stuff */
/* bits #0..15 in revision.h */
#define PARENT1 (1u<<16)
@@ -1018,6 +1020,8 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
#define STALE (1u<<18)
#define RESULT (1u<<19)
static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
static struct commit *interesting(struct commit_list *list)
{
while (list) {
@@ -1082,6 +1086,7 @@ static struct commit_list *merge_bases(struct commit *one, struct commit *two)
}
/* Clean up the result to remove stale ones */
free_commit_list(list);
list = result; result = NULL;
while (list) {
struct commit_list *n = list->next;
@@ -1097,7 +1102,6 @@ struct commit_list *get_merge_bases(struct commit *one,
struct commit *two,
int cleanup)
{
const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
struct commit_list *list;
struct commit **rslt;
struct commit_list *result;

120
config.c
View File

@@ -469,7 +469,15 @@ static int store_aux(const char* key, const char* value)
return 0;
}
static void store_write_section(int fd, const char* key)
static int write_error()
{
fprintf(stderr, "Failed to write new configuration file\n");
/* Same error code as "failed to rename". */
return 4;
}
static int store_write_section(int fd, const char* key)
{
const char *dot = strchr(key, '.');
int len1 = store.baselen, len2 = -1;
@@ -483,37 +491,74 @@ static void store_write_section(int fd, const char* key)
}
}
write(fd, "[", 1);
write(fd, key, len1);
if (write_in_full(fd, "[", 1) != 1 ||
write_in_full(fd, key, len1) != len1)
return 0;
if (len2 >= 0) {
write(fd, " \"", 2);
if (write_in_full(fd, " \"", 2) != 2)
return 0;
while (--len2 >= 0) {
unsigned char c = *++dot;
if (c == '"')
write(fd, "\\", 1);
write(fd, &c, 1);
if (write_in_full(fd, "\\", 1) != 1)
return 0;
if (write_in_full(fd, &c, 1) != 1)
return 0;
}
write(fd, "\"", 1);
if (write_in_full(fd, "\"", 1) != 1)
return 0;
}
write(fd, "]\n", 2);
if (write_in_full(fd, "]\n", 2) != 2)
return 0;
return 1;
}
static void store_write_pair(int fd, const char* key, const char* value)
static int store_write_pair(int fd, const char* key, const char* value)
{
int i;
int length = strlen(key+store.baselen+1);
int quote = 0;
write(fd, "\t", 1);
write(fd, key+store.baselen+1,
strlen(key+store.baselen+1));
write(fd, " = ", 3);
/* Check to see if the value needs to be quoted. */
if (value[0] == ' ')
quote = 1;
for (i = 0; value[i]; i++)
if (value[i] == ';' || value[i] == '#')
quote = 1;
if (value[i-1] == ' ')
quote = 1;
if (write_in_full(fd, "\t", 1) != 1 ||
write_in_full(fd, key+store.baselen+1, length) != length ||
write_in_full(fd, " = ", 3) != 3)
return 0;
if (quote && write_in_full(fd, "\"", 1) != 1)
return 0;
for (i = 0; value[i]; i++)
switch (value[i]) {
case '\n': write(fd, "\\n", 2); break;
case '\t': write(fd, "\\t", 2); break;
case '"': case '\\': write(fd, "\\", 1);
default: write(fd, value+i, 1);
}
write(fd, "\n", 1);
case '\n':
if (write_in_full(fd, "\\n", 2) != 2)
return 0;
break;
case '\t':
if (write_in_full(fd, "\\t", 2) != 2)
return 0;
break;
case '"':
case '\\':
if (write_in_full(fd, "\\", 1) != 1)
return 0;
default:
if (write_in_full(fd, value+i, 1) != 1)
return 0;
break;
}
if (quote && write_in_full(fd, "\"", 1) != 1)
return 0;
if (write_in_full(fd, "\n", 1) != 1)
return 0;
return 1;
}
static int find_beginning_of_line(const char* contents, int size,
@@ -653,8 +698,11 @@ int git_config_set_multivar(const char* key, const char* value,
}
store.key = (char*)key;
store_write_section(fd, key);
store_write_pair(fd, key, value);
if (!store_write_section(fd, key) ||
!store_write_pair(fd, key, value)) {
ret = write_error();
goto out_free;
}
} else{
struct stat st;
char* contents;
@@ -734,10 +782,10 @@ int git_config_set_multivar(const char* key, const char* value,
/* write the first part of the config */
if (copy_end > copy_begin) {
write(fd, contents + copy_begin,
write_in_full(fd, contents + copy_begin,
copy_end - copy_begin);
if (new_line)
write(fd, "\n", 1);
write_in_full(fd, "\n", 1);
}
copy_begin = store.offset[i];
}
@@ -745,13 +793,19 @@ int git_config_set_multivar(const char* key, const char* value,
/* write the pair (value == NULL means unset) */
if (value != NULL) {
if (store.state == START)
store_write_section(fd, key);
store_write_pair(fd, key, value);
if (!store_write_section(fd, key)) {
ret = write_error();
goto out_free;
}
if (!store_write_pair(fd, key, value)) {
ret = write_error();
goto out_free;
}
}
/* write the rest of the config */
if (copy_begin < st.st_size)
write(fd, contents + copy_begin,
write_in_full(fd, contents + copy_begin,
st.st_size - copy_begin);
munmap(contents, st.st_size);
@@ -805,6 +859,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
while (fgets(buf, sizeof(buf), config_file)) {
int i;
int length;
for (i = 0; buf[i] && isspace(buf[i]); i++)
; /* do nothing */
if (buf[i] == '[') {
@@ -835,15 +890,22 @@ int git_config_rename_section(const char *old_name, const char *new_name)
/* old_name matches */
ret++;
store.baselen = strlen(new_name);
store_write_section(out_fd, new_name);
if (!store_write_section(out_fd, new_name)) {
ret = write_error();
goto out;
}
continue;
}
}
write(out_fd, buf, strlen(buf));
length = strlen(buf);
if (write_in_full(out_fd, buf, length) != length) {
ret = write_error();
goto out;
}
}
fclose(config_file);
if (close(out_fd) || commit_lock_file(lock) < 0)
ret = error("Cannot commit config file!");
ret = error("Cannot commit config file!");
out:
free(config_filename);
return ret;

View File

@@ -102,7 +102,7 @@ static void logreport(int priority, const char *err, va_list params)
buf[buflen++] = '\n';
buf[buflen] = '\0';
write(2, buf, buflen);
write_in_full(2, buf, buflen);
}
static void logerror(const char *err, ...)

2
diff.c
View File

@@ -1403,7 +1403,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
fd = git_mkstemp(temp->tmp_path, TEMPFILE_PATH_LEN, ".diff_XXXXXX");
if (fd < 0)
die("unable to create temp-file");
if (write(fd, blob, size) != size)
if (write_in_full(fd, blob, size) != size)
die("unable to write temp-file");
close(fd);
temp->name = temp->tmp_path;

2
dir.c
View File

@@ -142,7 +142,7 @@ static int add_excludes_from_file_1(const char *fname,
return 0;
}
buf = xmalloc(size+1);
if (read(fd, buf, size) != size)
if (read_in_full(fd, buf, size) != size)
goto err;
close(fd);

View File

@@ -89,7 +89,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
return error("git-checkout-index: unable to create file %s (%s)",
path, strerror(errno));
}
wrote = write(fd, new, size);
wrote = write_in_full(fd, new, size);
close(fd);
free(new);
if (wrote != size)
@@ -104,7 +104,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
return error("git-checkout-index: unable to create "
"file %s (%s)", path, strerror(errno));
}
wrote = write(fd, new, size);
wrote = write_in_full(fd, new, size);
close(fd);
free(new);
if (wrote != size)

View File

@@ -399,7 +399,9 @@ static void fsck_dir(int i, char *path)
static int default_refs;
static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1, char *datail, void *cb_data)
static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
const char *email, unsigned long timestamp, int tz,
const char *message, void *cb_data)
{
struct object *obj;

View File

@@ -2,7 +2,7 @@
#
# Copyright (c) 2005, 2006 Junio C Hamano
USAGE='[--signoff] [--dotest=<dir>] [--utf8] [--binary] [--3way]
USAGE='[--signoff] [--dotest=<dir>] [--utf8 | --no-utf8] [--binary] [--3way]
[--interactive] [--whitespace=<option>] <mbox>...
or, when resuming [--skip | --resolved]'
. git-sh-setup
@@ -105,7 +105,7 @@ It does not apply to blobs recorded in its index."
}
prec=4
dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg=
dotest=.dotest sign= utf8=t keep= skip= interactive= resolved= binary= ws= resolvemsg=
while case "$#" in 0) break;; esac
do
@@ -128,7 +128,9 @@ do
-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
sign=t; shift ;;
-u|--u|--ut|--utf|--utf8)
utf8=t; shift ;;
shift ;; # this is now default
--no-u|--no-ut|--no-utf|--no-utf8)
utf8=; shift ;;
-k|--k|--ke|--kee|--keep)
keep=t; shift ;;

View File

@@ -628,7 +628,7 @@ then
if test -z "$quiet"
then
echo "Created${initial_commit:+ initial} commit $commit"
git-diff-tree --shortstat --summary --root --no-commit-id HEAD
git-diff-tree --shortstat --summary --root --no-commit-id HEAD --
fi
fi

View File

@@ -1181,12 +1181,15 @@ sub req_ci
$filename = filecleanup($filename);
my $meta = $updater->getmeta($filename);
unless (defined $meta->{revision}) {
$meta->{revision} = 1;
}
my ( $filepart, $dirpart ) = filenamesplit($filename, 1);
$log->debug("Checked-in $dirpart : $filename");
if ( $meta->{filehash} eq "deleted" )
if ( defined $meta->{filehash} && $meta->{filehash} eq "deleted" )
{
print "Remove-entry $dirpart\n";
print "$filename\n";
@@ -2184,7 +2187,10 @@ sub update
# first lets get the commit list
$ENV{GIT_DIR} = $self->{git_path};
my $commitinfo = `git-cat-file commit $self->{module} 2>&1`;
my $commitsha1 = `git rev-parse $self->{module}`;
chomp $commitsha1;
my $commitinfo = `git cat-file commit $self->{module} 2>&1`;
unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ )
{
die("Invalid module '$self->{module}'");
@@ -2194,6 +2200,10 @@ sub update
my $git_log;
my $lastcommit = $self->_get_prop("last_commit");
if (defined $lastcommit && $lastcommit eq $commitsha1) { # up-to-date
return 1;
}
# Start exclusive lock here...
$self->{dbh}->begin_work() or die "Cannot lock database for BEGIN";

View File

@@ -1,284 +0,0 @@
#!/usr/bin/perl
#
# REuse REcorded REsolve. This tool records a conflicted automerge
# result and its hand resolution, and helps to resolve future
# automerge that results in the same conflict.
#
# To enable this feature, create a directory 'rr-cache' under your
# .git/ directory.
use Digest;
use File::Path;
use File::Copy;
my $git_dir = $::ENV{GIT_DIR} || ".git";
my $rr_dir = "$git_dir/rr-cache";
my $merge_rr = "$git_dir/rr-cache/MERGE_RR";
my %merge_rr = ();
sub read_rr {
if (!-f $merge_rr) {
%merge_rr = ();
return;
}
my $in;
local $/ = "\0";
open $in, "<$merge_rr" or die "$!: $merge_rr";
while (<$in>) {
chomp;
my ($name, $path) = /^([0-9a-f]{40})\t(.*)$/s;
$merge_rr{$path} = $name;
}
close $in;
}
sub write_rr {
my $out;
open $out, ">$merge_rr" or die "$!: $merge_rr";
for my $path (sort keys %merge_rr) {
my $name = $merge_rr{$path};
print $out "$name\t$path\0";
}
close $out;
}
sub compute_conflict_name {
my ($path) = @_;
my @side = ();
my $in;
open $in, "<$path" or die "$!: $path";
my $sha1 = Digest->new("SHA-1");
my $hunk = 0;
while (<$in>) {
if (/^<<<<<<< .*/) {
$hunk++;
@side = ([], undef);
}
elsif (/^=======$/) {
$side[1] = [];
}
elsif (/^>>>>>>> .*/) {
my ($one, $two);
$one = join('', @{$side[0]});
$two = join('', @{$side[1]});
if ($two le $one) {
($one, $two) = ($two, $one);
}
$sha1->add($one);
$sha1->add("\0");
$sha1->add($two);
$sha1->add("\0");
@side = ();
}
elsif (@side == 0) {
next;
}
elsif (defined $side[1]) {
push @{$side[1]}, $_;
}
else {
push @{$side[0]}, $_;
}
}
close $in;
return ($sha1->hexdigest, $hunk);
}
sub record_preimage {
my ($path, $name) = @_;
my @side = ();
my ($in, $out);
open $in, "<$path" or die "$!: $path";
open $out, ">$name" or die "$!: $name";
while (<$in>) {
if (/^<<<<<<< .*/) {
@side = ([], undef);
}
elsif (/^=======$/) {
$side[1] = [];
}
elsif (/^>>>>>>> .*/) {
my ($one, $two);
$one = join('', @{$side[0]});
$two = join('', @{$side[1]});
if ($two le $one) {
($one, $two) = ($two, $one);
}
print $out "<<<<<<<\n";
print $out $one;
print $out "=======\n";
print $out $two;
print $out ">>>>>>>\n";
@side = ();
}
elsif (@side == 0) {
print $out $_;
}
elsif (defined $side[1]) {
push @{$side[1]}, $_;
}
else {
push @{$side[0]}, $_;
}
}
close $out;
close $in;
}
sub find_conflict {
my $in;
local $/ = "\0";
my $pid = open($in, '-|');
die "$!" unless defined $pid;
if (!$pid) {
exec(qw(git ls-files -z -u)) or die "$!: ls-files";
}
my %path = ();
my @path = ();
while (<$in>) {
chomp;
my ($mode, $sha1, $stage, $path) =
/^([0-7]+) ([0-9a-f]{40}) ([123])\t(.*)$/s;
$path{$path} |= (1 << $stage);
}
close $in;
while (my ($path, $status) = each %path) {
if ($status == 14) { push @path, $path; }
}
return @path;
}
sub merge {
my ($name, $path) = @_;
record_preimage($path, "$rr_dir/$name/thisimage");
unless (system('git', 'merge-file', map { "$rr_dir/$name/${_}image" }
qw(this pre post))) {
my $in;
open $in, "<$rr_dir/$name/thisimage" or
die "$!: $name/thisimage";
my $out;
open $out, ">$path" or die "$!: $path";
while (<$in>) { print $out $_; }
close $in;
close $out;
return 1;
}
return 0;
}
sub garbage_collect_rerere {
# We should allow specifying these from the command line and
# that is why the caller gives @ARGV to us, but I am lazy.
my $cutoff_noresolve = 15; # two weeks
my $cutoff_resolve = 60; # two months
my @to_remove;
while (<$rr_dir/*/preimage>) {
my ($dir) = /^(.*)\/preimage$/;
my $cutoff = ((-f "$dir/postimage")
? $cutoff_resolve
: $cutoff_noresolve);
my $age = -M "$_";
if ($cutoff <= $age) {
push @to_remove, $dir;
}
}
if (@to_remove) {
rmtree(\@to_remove);
}
}
-d "$rr_dir" || exit(0);
read_rr();
if (@ARGV) {
my $arg = shift @ARGV;
if ($arg eq 'clear') {
for my $path (keys %merge_rr) {
my $name = $merge_rr{$path};
if (-d "$rr_dir/$name" &&
! -f "$rr_dir/$name/postimage") {
rmtree(["$rr_dir/$name"]);
}
}
unlink $merge_rr;
}
elsif ($arg eq 'status') {
for my $path (keys %merge_rr) {
print $path, "\n";
}
}
elsif ($arg eq 'diff') {
for my $path (keys %merge_rr) {
my $name = $merge_rr{$path};
system('diff', ((@ARGV == 0) ? ('-u') : @ARGV),
'-L', "a/$path", '-L', "b/$path",
"$rr_dir/$name/preimage", $path);
}
}
elsif ($arg eq 'gc') {
garbage_collect_rerere(@ARGV);
}
else {
die "$0 unknown command: $arg\n";
}
exit 0;
}
my %conflict = map { $_ => 1 } find_conflict();
# MERGE_RR records paths with conflicts immediately after merge
# failed. Some of the conflicted paths might have been hand resolved
# in the working tree since then, but the initial run would catch all
# and register their preimages.
for my $path (keys %conflict) {
# This path has conflict. If it is not recorded yet,
# record the pre-image.
if (!exists $merge_rr{$path}) {
my ($name, $hunk) = compute_conflict_name($path);
next unless ($hunk);
$merge_rr{$path} = $name;
if (! -d "$rr_dir/$name") {
mkpath("$rr_dir/$name", 0, 0777);
print STDERR "Recorded preimage for '$path'\n";
record_preimage($path, "$rr_dir/$name/preimage");
}
}
}
# Now some of the paths that had conflicts earlier might have been
# hand resolved. Others may be similar to a conflict already that
# was resolved before.
for my $path (keys %merge_rr) {
my $name = $merge_rr{$path};
# We could resolve this automatically if we have images.
if (-f "$rr_dir/$name/preimage" &&
-f "$rr_dir/$name/postimage") {
if (merge($name, $path)) {
print STDERR "Resolved '$path' using previous resolution.\n";
# Then we do not have to worry about this path
# anymore.
delete $merge_rr{$path};
next;
}
}
# Let's see if we have resolved it.
(undef, my $hunk) = compute_conflict_name($path);
next if ($hunk);
print STDERR "Recorded resolution for '$path'.\n";
copy($path, "$rr_dir/$name/postimage");
# And we do not have to worry about this path anymore.
delete $merge_rr{$path};
}
# Write out the rest.
write_rr();

View File

@@ -71,7 +71,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
int posn = 0;
struct object_request *obj_req = (struct object_request *)data;
do {
ssize_t retval = write(obj_req->local,
ssize_t retval = xwrite(obj_req->local,
(char *) ptr + posn, size - posn);
if (retval < 0)
return posn;
@@ -175,7 +175,7 @@ static void start_object_request(struct object_request *obj_req)
prevlocal = open(prevfile, O_RDONLY);
if (prevlocal != -1) {
do {
prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
if (prev_read>0) {
if (fwrite_sha1_file(prev_buf,
1,

View File

@@ -195,7 +195,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
int posn = 0;
struct transfer_request *request = (struct transfer_request *)data;
do {
ssize_t retval = write(request->local_fileno,
ssize_t retval = xwrite(request->local_fileno,
(char *) ptr + posn, size - posn);
if (retval < 0)
return posn;
@@ -288,7 +288,7 @@ static void start_fetch_loose(struct transfer_request *request)
prevlocal = open(prevfile, O_RDONLY);
if (prevlocal != -1) {
do {
prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
if (prev_read>0) {
if (fwrite_sha1_file(prev_buf,
1,

View File

@@ -224,7 +224,7 @@ socket_perror( const char *func, Socket_t *sock, int ret )
static int
socket_read( Socket_t *sock, char *buf, int len )
{
int n = read( sock->fd, buf, len );
int n = xread( sock->fd, buf, len );
if (n <= 0) {
socket_perror( "read", sock, n );
close( sock->fd );
@@ -236,7 +236,7 @@ socket_read( Socket_t *sock, char *buf, int len )
static int
socket_write( Socket_t *sock, const char *buf, int len )
{
int n = write( sock->fd, buf, len );
int n = write_in_full( sock->fd, buf, len );
if (n != len) {
socket_perror( "write", sock, n );
close( sock->fd );
@@ -390,7 +390,7 @@ arc4_init( void )
fprintf( stderr, "Fatal: no random number source available.\n" );
exit( 3 );
}
if (read( fd, dat, 128 ) != 128) {
if (read_in_full( fd, dat, 128 ) != 128) {
fprintf( stderr, "Fatal: cannot read random number source.\n" );
exit( 3 );
}

View File

@@ -638,7 +638,7 @@ static void readjust_pack_header_and_sha1(unsigned char *sha1)
/* Rewrite pack header with updated object number */
if (lseek(output_fd, 0, SEEK_SET) != 0)
die("cannot seek back: %s", strerror(errno));
if (xread(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
if (read_in_full(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
die("cannot read pack header back: %s", strerror(errno));
hdr.hdr_entries = htonl(nr_objects);
if (lseek(output_fd, 0, SEEK_SET) != 0)
@@ -814,7 +814,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
char buf[48];
int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
report, sha1_to_hex(sha1));
xwrite(1, buf, len);
write_in_full(1, buf, len);
/*
* Let's just mimic git-unpack-objects here and write

View File

@@ -184,7 +184,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
fprintf(stderr, "cannot open %s\n", filename);
return -1;
}
if (read(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) {
if (read_in_full(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) {
close(ifd);
fprintf(stderr, "cannot read from %s\n", filename);
return -1;

View File

@@ -517,7 +517,7 @@ static int mkdir_p(const char *path, unsigned long mode)
static void flush_buffer(int fd, const char *buf, unsigned long size)
{
while (size > 0) {
long ret = xwrite(fd, buf, size);
long ret = write_in_full(fd, buf, size);
if (ret < 0) {
/* Ignore epipe */
if (errno == EPIPE)

2
path.c
View File

@@ -114,7 +114,7 @@ int validate_headref(const char *path)
fd = open(path, O_RDONLY);
if (fd < 0)
return -1;
len = read(fd, buffer, sizeof(buffer)-1);
len = read_in_full(fd, buffer, sizeof(buffer)-1);
close(fd);
/*

View File

@@ -104,7 +104,9 @@ static void walk_commit_list(struct rev_info *revs)
}
}
static int add_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1, char *datail, void *cb_data)
static int add_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
const char *email, unsigned long timestamp, int tz,
const char *message, void *cb_data)
{
struct object *object;
struct rev_info *revs = (struct rev_info *)cb_data;

View File

@@ -870,7 +870,7 @@ static int ce_write_flush(SHA_CTX *context, int fd)
unsigned int buffered = write_buffer_len;
if (buffered) {
SHA1_Update(context, write_buffer, buffered);
if (write(fd, write_buffer, buffered) != buffered)
if (write_in_full(fd, write_buffer, buffered) != buffered)
return -1;
write_buffer_len = 0;
}
@@ -919,7 +919,7 @@ static int ce_flush(SHA_CTX *context, int fd)
/* Flush first if not enough space for SHA1 signature */
if (left + 20 > WRITE_BUFFER_SIZE) {
if (write(fd, write_buffer, left) != left)
if (write_in_full(fd, write_buffer, left) != left)
return -1;
left = 0;
}
@@ -927,7 +927,7 @@ static int ce_flush(SHA_CTX *context, int fd)
/* Append the SHA1 signature at the end */
SHA1_Final(write_buffer + left, context);
left += 20;
return (write(fd, write_buffer, left) != left) ? -1 : 0;
return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0;
}
static void ce_smudge_racily_clean_entry(struct cache_entry *ce)

36
refs.c
View File

@@ -284,7 +284,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
fd = open(path, O_RDONLY);
if (fd < 0)
return NULL;
len = read(fd, buffer, sizeof(buffer)-1);
len = read_in_full(fd, buffer, sizeof(buffer)-1);
close(fd);
/*
@@ -332,7 +332,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master)
}
lockpath = mkpath("%s.lock", git_HEAD);
fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
written = write(fd, ref, len);
written = write_in_full(fd, ref, len);
close(fd);
if (written != len) {
unlink(lockpath);
@@ -971,7 +971,7 @@ static int log_ref_write(struct ref_lock *lock,
sha1_to_hex(sha1),
committer);
}
written = len <= maxlen ? write(logfd, logrec, len) : -1;
written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
free(logrec);
close(logfd);
if (written != len)
@@ -990,8 +990,8 @@ int write_ref_sha1(struct ref_lock *lock,
unlock_ref(lock);
return 0;
}
if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
write(lock->lock_fd, &term, 1) != 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) {
error("Couldn't write %s", lock->lk->filename);
unlock_ref(lock);
@@ -1100,7 +1100,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
return 0;
}
void for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
{
const char *logfile;
FILE *logfp;
@@ -1109,19 +1109,35 @@ void for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
logfile = git_path("logs/%s", ref);
logfp = fopen(logfile, "r");
if (!logfp)
return;
return -1;
while (fgets(buf, sizeof(buf), logfp)) {
unsigned char osha1[20], nsha1[20];
int len;
char *email_end, *message;
unsigned long timestamp;
int len, ret, tz;
/* old SP new SP name <email> SP time TAB msg LF */
len = strlen(buf);
if (len < 83 || buf[len-1] != '\n' ||
get_sha1_hex(buf, osha1) || buf[40] != ' ' ||
get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ')
get_sha1_hex(buf + 41, nsha1) || buf[81] != ' ' ||
!(email_end = strchr(buf + 82, '>')) ||
email_end[1] != ' ' ||
!(timestamp = strtoul(email_end + 2, &message, 10)) ||
!message || message[0] != ' ' ||
(message[1] != '+' && message[1] != '-') ||
!isdigit(message[2]) || !isdigit(message[3]) ||
!isdigit(message[4]) || !isdigit(message[5]) ||
message[6] != '\t')
continue; /* corrupt? */
fn(osha1, nsha1, buf+82, cb_data);
email_end[1] = '\0';
tz = strtol(message + 1, NULL, 10);
message += 7;
ret = fn(osha1, nsha1, buf+82, timestamp, tz, message, cb_data);
if (ret)
return ret;
}
fclose(logfp);
return 0;
}

4
refs.h
View File

@@ -45,8 +45,8 @@ extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, cons
extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1);
/* iterate over reflog entries */
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, char *, void *);
void for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data);
/** Returns 0 if target has the right format for a ref. **/
extern int check_ref_format(const char *target);

View File

@@ -505,7 +505,9 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
}
}
static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1, char *detail, void *cb_data)
static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
const char *email, unsigned long timestamp, int tz,
const char *message, void *cb_data)
{
handle_one_reflog_commit(osha1, cb_data);
handle_one_reflog_commit(nsha1, cb_data);

View File

@@ -65,14 +65,14 @@ static int pack_objects(int fd, struct ref *refs)
memcpy(buf + 1, sha1_to_hex(refs->old_sha1), 40);
buf[0] = '^';
buf[41] = '\n';
if (!write_in_full(pipe_fd[1], buf, 42,
if (!write_or_whine(pipe_fd[1], buf, 42,
"send-pack: send refs"))
break;
}
if (!is_null_sha1(refs->new_sha1)) {
memcpy(buf, sha1_to_hex(refs->new_sha1), 40);
buf[40] = '\n';
if (!write_in_full(pipe_fd[1], buf, 41,
if (!write_or_whine(pipe_fd[1], buf, 41,
"send-pack: send refs"))
break;
}

View File

@@ -1611,20 +1611,13 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
static int write_buffer(int fd, const void *buf, size_t len)
{
while (len) {
ssize_t size;
ssize_t size;
size = write(fd, buf, len);
if (!size)
return error("file write: disk full");
if (size < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return error("file write error (%s)", strerror(errno));
}
len -= size;
buf = (char *) buf + size;
}
size = write_in_full(fd, buf, len);
if (!size)
return error("file write: disk full");
if (size < 0)
return error("file write error (%s)", strerror(errno));
return 0;
}
@@ -1869,7 +1862,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
if (ret != Z_OK)
break;
}
size = read(fd, buffer + *bufposn, bufsize - *bufposn);
size = xread(fd, buffer + *bufposn, bufsize - *bufposn);
if (size <= 0) {
close(local);
unlink(tmpfile);

View File

@@ -20,22 +20,6 @@ static int fd_out;
static unsigned char remote_version;
static unsigned char local_version = 1;
static ssize_t force_write(int fd, void *buffer, size_t length)
{
ssize_t ret = 0;
while (ret < length) {
ssize_t size = write(fd, (char *) buffer + ret, length - ret);
if (size < 0) {
return size;
}
if (size == 0) {
return ret;
}
ret += size;
}
return ret;
}
static int prefetches;
static struct object_list *in_transit;
@@ -53,8 +37,9 @@ void prefetch(unsigned char *sha1)
node->item = lookup_unknown_object(sha1);
*end_of_transit = node;
end_of_transit = &node->next;
force_write(fd_out, &type, 1);
force_write(fd_out, sha1, 20);
/* XXX: what if these writes fail? */
write_in_full(fd_out, &type, 1);
write_in_full(fd_out, sha1, 20);
prefetches++;
}
@@ -82,7 +67,7 @@ int fetch(unsigned char *sha1)
remote = conn_buf[0];
memmove(conn_buf, conn_buf + 1, --conn_buf_posn);
} else {
if (read(fd_in, &remote, 1) < 1)
if (xread(fd_in, &remote, 1) < 1)
return -1;
}
/* fprintf(stderr, "Got %d\n", remote); */
@@ -97,9 +82,11 @@ int fetch(unsigned char *sha1)
static int get_version(void)
{
char type = 'v';
write(fd_out, &type, 1);
write(fd_out, &local_version, 1);
if (read(fd_in, &remote_version, 1) < 1) {
if (write_in_full(fd_out, &type, 1) != 1 ||
write_in_full(fd_out, &local_version, 1)) {
return error("Couldn't request version from remote end");
}
if (xread(fd_in, &remote_version, 1) < 1) {
return error("Couldn't read version from remote end");
}
return 0;
@@ -109,12 +96,17 @@ int fetch_ref(char *ref, unsigned char *sha1)
{
signed char remote;
char type = 'r';
write(fd_out, &type, 1);
write(fd_out, ref, strlen(ref) + 1);
read(fd_in, &remote, 1);
int length = strlen(ref) + 1;
if (write_in_full(fd_out, &type, 1) != 1 ||
write_in_full(fd_out, ref, length) != length)
return -1;
if (read_in_full(fd_in, &remote, 1) != 1)
return -1;
if (remote < 0)
return remote;
read(fd_in, sha1, 20);
if (read_in_full(fd_in, sha1, 20) != 20)
return -1;
return 0;
}

View File

@@ -21,17 +21,14 @@ static int serve_object(int fd_in, int fd_out) {
ssize_t size;
unsigned char sha1[20];
signed char remote;
int posn = 0;
do {
size = read(fd_in, sha1 + posn, 20 - posn);
if (size < 0) {
perror("git-ssh-upload: read ");
return -1;
}
if (!size)
return -1;
posn += size;
} while (posn < 20);
size = read_in_full(fd_in, sha1, 20);
if (size < 0) {
perror("git-ssh-upload: read ");
return -1;
}
if (!size)
return -1;
if (verbose)
fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1));
@@ -44,7 +41,8 @@ static int serve_object(int fd_in, int fd_out) {
remote = -1;
}
write(fd_out, &remote, 1);
if (write_in_full(fd_out, &remote, 1) != 1)
return 0;
if (remote < 0)
return 0;
@@ -54,9 +52,9 @@ static int serve_object(int fd_in, int fd_out) {
static int serve_version(int fd_in, int fd_out)
{
if (read(fd_in, &remote_version, 1) < 1)
if (xread(fd_in, &remote_version, 1) < 1)
return -1;
write(fd_out, &local_version, 1);
write_in_full(fd_out, &local_version, 1);
return 0;
}
@@ -67,7 +65,7 @@ static int serve_ref(int fd_in, int fd_out)
int posn = 0;
signed char remote = 0;
do {
if (read(fd_in, ref + posn, 1) < 1)
if (posn >= PATH_MAX || xread(fd_in, ref + posn, 1) < 1)
return -1;
posn++;
} while (ref[posn - 1]);
@@ -77,10 +75,11 @@ static int serve_ref(int fd_in, int fd_out)
if (get_ref_sha1(ref, sha1))
remote = -1;
write(fd_out, &remote, 1);
if (write_in_full(fd_out, &remote, 1) != 1)
return 0;
if (remote)
return 0;
write(fd_out, sha1, 20);
write_in_full(fd_out, sha1, 20);
return 0;
}
@@ -89,7 +88,7 @@ static void service(int fd_in, int fd_out) {
char type;
int retval;
do {
retval = read(fd_in, &type, 1);
retval = xread(fd_in, &type, 1);
if (retval < 1) {
if (retval < 0)
perror("git-ssh-upload: read ");

View File

@@ -401,5 +401,22 @@ test_expect_success numbers '
test z1048576 = "z$m"
'
rm .git/config
git-repo-config quote.leading " test"
git-repo-config quote.ending "test "
git-repo-config quote.semicolon "test;test"
git-repo-config quote.hash "test#test"
cat > expect << EOF
[quote]
leading = " test"
ending = "test "
semicolon = "test;test"
hash = "test#test"
EOF
test_expect_success 'quoting' 'cmp .git/config expect'
test_done

View File

@@ -34,7 +34,7 @@ test_expect_success \
'see if a branch still exists when packed' \
'git-branch b &&
git-pack-refs --all &&
rm .git/refs/heads/b &&
rm -f .git/refs/heads/b &&
echo "$SHA1 refs/heads/b" >expect &&
git-show-ref b >result &&
diff expect result'

View File

@@ -68,7 +68,7 @@ int main(int argc, char *argv[])
}
fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (fd < 0 || write(fd, out_buf, out_size) != out_size) {
if (fd < 0 || write_in_full(fd, out_buf, out_size) != out_size) {
perror(argv[4]);
return 1;
}

View File

@@ -101,7 +101,7 @@ void trace_printf(const char *format, ...)
nfvasprintf(&trace_str, format, rest);
va_end(rest);
write_or_whine(fd, trace_str, strlen(trace_str), err_msg);
write_or_whine_pipe(fd, trace_str, strlen(trace_str), err_msg);
free(trace_str);
@@ -139,7 +139,7 @@ void trace_argv_printf(const char **argv, int count, const char *format, ...)
strncpy(trace_str + format_len, argv_str, argv_len);
strcpy(trace_str + trace_len - 1, "\n");
write_or_whine(fd, trace_str, trace_len, err_msg);
write_or_whine_pipe(fd, trace_str, trace_len, err_msg);
free(argv_str);
free(format_str);

View File

@@ -17,7 +17,7 @@ static char *create_temp_file(unsigned char *sha1)
fd = mkstemp(path);
if (fd < 0)
die("unable to create temp-file");
if (write(fd, buf, size) != size)
if (write_in_full(fd, buf, size) != size)
die("unable to write temp-file");
close(fd);
return path;

View File

@@ -55,6 +55,7 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
/* emergency quit */
fd = 2;
if (fd == 2) {
/* XXX: are we happy to lose stuff here? */
xwrite(fd, data, sz);
return sz;
}
@@ -242,7 +243,7 @@ static void create_pack_file(void)
*cp++ = buffered;
outsz++;
}
sz = read(pu_pipe[0], cp,
sz = xread(pu_pipe[0], cp,
sizeof(data) - outsz);
if (0 < sz)
;
@@ -267,7 +268,7 @@ static void create_pack_file(void)
/* Status ready; we ship that in the side-band
* or dump to the standard error.
*/
sz = read(pe_pipe[0], progress,
sz = xread(pe_pipe[0], progress,
sizeof(progress));
if (0 < sz)
send_client_data(2, progress, sz);

View File

@@ -1,83 +1,107 @@
#include "cache.h"
void read_or_die(int fd, void *buf, size_t count)
int read_in_full(int fd, void *buf, size_t count)
{
char *p = buf;
ssize_t loaded;
ssize_t total = 0;
ssize_t loaded = 0;
while (count > 0) {
loaded = xread(fd, p, count);
if (loaded == 0)
die("unexpected end of file");
else if (loaded < 0)
die("read error (%s)", strerror(errno));
if (loaded <= 0) {
if (total)
return total;
else
return loaded;
}
count -= loaded;
p += loaded;
total += loaded;
}
return total;
}
void read_or_die(int fd, void *buf, size_t count)
{
ssize_t loaded;
loaded = read_in_full(fd, buf, count);
if (loaded == 0)
die("unexpected end of file");
else if (loaded < 0)
die("read error (%s)", strerror(errno));
}
int write_in_full(int fd, const void *buf, size_t count)
{
const char *p = buf;
ssize_t total = 0;
ssize_t written = 0;
while (count > 0) {
written = xwrite(fd, p, count);
if (written <= 0) {
if (total)
return total;
else
return written;
}
count -= written;
p += written;
total += written;
}
return total;
}
void write_or_die(int fd, const void *buf, size_t count)
{
const char *p = buf;
ssize_t written;
while (count > 0) {
written = xwrite(fd, p, count);
if (written == 0)
die("disk full?");
else if (written < 0) {
if (errno == EPIPE)
exit(0);
die("write error (%s)", strerror(errno));
}
count -= written;
p += written;
written = write_in_full(fd, buf, count);
if (written == 0)
die("disk full?");
else if (written < 0) {
if (errno == EPIPE)
exit(0);
die("write error (%s)", strerror(errno));
}
}
int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg)
{
ssize_t written;
written = write_in_full(fd, buf, count);
if (written == 0) {
fprintf(stderr, "%s: disk full?\n", msg);
return 0;
}
else if (written < 0) {
if (errno == EPIPE)
exit(0);
fprintf(stderr, "%s: write error (%s)\n",
msg, strerror(errno));
return 0;
}
return 1;
}
int write_or_whine(int fd, const void *buf, size_t count, const char *msg)
{
const char *p = buf;
ssize_t written;
while (count > 0) {
written = xwrite(fd, p, count);
if (written == 0) {
fprintf(stderr, "%s: disk full?\n", msg);
return 0;
}
else if (written < 0) {
if (errno == EPIPE)
exit(0);
fprintf(stderr, "%s: write error (%s)\n",
msg, strerror(errno));
return 0;
}
count -= written;
p += written;
}
return 1;
}
int write_in_full(int fd, const void *buf, size_t count, const char *msg)
{
const char *p = buf;
ssize_t written;
while (count > 0) {
written = xwrite(fd, p, count);
if (written == 0) {
fprintf(stderr, "%s: disk full?\n", msg);
return 0;
}
else if (written < 0) {
fprintf(stderr, "%s: write error (%s)\n",
msg, strerror(errno));
return 0;
}
count -= written;
p += written;
written = write_in_full(fd, buf, count);
if (written == 0) {
fprintf(stderr, "%s: disk full?\n", msg);
return 0;
}
else if (written < 0) {
fprintf(stderr, "%s: write error (%s)\n",
msg, strerror(errno));
return 0;
}
return 1;