From fa0cdab537b1ae635b5a64cddd29cddf2dfc4a1b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 4 Apr 2006 22:57:15 -0700 Subject: [PATCH 1/4] parse_date(): fix parsing 03/10/2006 The comment associated with the date parsing code for three numbers separated with slashes or dashes implied we wanted to interpret using this order: yyyy-mm-dd yyyy-dd-mm mm-dd-yy dd-mm-yy However, the actual code had the last two wrong, and making it prefer dd-mm-yy format over mm-dd-yy. Signed-off-by: Junio C Hamano --- date.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/date.c b/date.c index 416ea579a3..18a07103d8 100644 --- a/date.c +++ b/date.c @@ -257,10 +257,10 @@ static int match_multi_number(unsigned long num, char c, const char *date, char break; } /* mm/dd/yy ? */ - if (is_date(num3, num2, num, tm)) + if (is_date(num3, num, num2, tm)) break; /* dd/mm/yy ? */ - if (is_date(num3, num, num2, tm)) + if (is_date(num3, num2, num, tm)) break; return 0; } From d9ea73e0564c7db8d791fe6b03c976ce57c9b079 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 5 Apr 2006 02:03:58 -0700 Subject: [PATCH 2/4] combine-diff: refactor built-in xdiff interface. This refactors the line-by-line callback mechanism used in combine-diff so that other programs can reuse it more easily. Signed-off-by: Junio C Hamano --- Makefile | 2 +- combine-diff.c | 52 ++++++------------------------------------ xdiff-interface.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ xdiff-interface.h | 18 +++++++++++++++ 4 files changed, 84 insertions(+), 46 deletions(-) create mode 100644 xdiff-interface.c create mode 100644 xdiff-interface.h diff --git a/Makefile b/Makefile index 145099adaa..7030370c6f 100644 --- a/Makefile +++ b/Makefile @@ -208,7 +208,7 @@ LIB_OBJS = \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ - fetch-clone.o revision.o pager.o tree-walk.o \ + fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \ $(DIFF_OBJS) GITLIBS = $(LIB_FILE) $(XDIFF_LIB) diff --git a/combine-diff.c b/combine-diff.c index 11f5143eec..e17afd1096 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -4,7 +4,7 @@ #include "diff.h" #include "diffcore.h" #include "quote.h" -#include "xdiff/xdiff.h" +#include "xdiff-interface.h" static int uninteresting(struct diff_filepair *p) { @@ -195,8 +195,8 @@ static void append_lost(struct sline *sline, int n, const char *line, int len) } struct combine_diff_state { - char *remainder; - unsigned long remainder_size; + struct xdiff_emit_state xm; + unsigned int lno, ob, on, nb, nn; unsigned long nmask; int num_parent; @@ -205,10 +205,9 @@ struct combine_diff_state { struct sline *lost_bucket; }; -static void consume_line(struct combine_diff_state *state, - char *line, - unsigned long len) +static void consume_line(void *state_, char *line, unsigned long len) { + struct combine_diff_state *state = state_; if (5 < len && !memcmp("@@ -", line, 4)) { if (parse_hunk_header(line, len, &state->ob, &state->on, @@ -249,41 +248,6 @@ static void consume_line(struct combine_diff_state *state, } } -static int combine_diff_outf(void *priv_, mmbuffer_t *mb, int nbuf) -{ - struct combine_diff_state *priv = priv_; - int i; - for (i = 0; i < nbuf; i++) { - if (mb[i].ptr[mb[i].size-1] != '\n') { - /* Incomplete line */ - priv->remainder = realloc(priv->remainder, - priv->remainder_size + - mb[i].size); - memcpy(priv->remainder + priv->remainder_size, - mb[i].ptr, mb[i].size); - priv->remainder_size += mb[i].size; - continue; - } - - /* we have a complete line */ - if (!priv->remainder) { - consume_line(priv, mb[i].ptr, mb[i].size); - continue; - } - priv->remainder = realloc(priv->remainder, - priv->remainder_size + - mb[i].size); - memcpy(priv->remainder + priv->remainder_size, - mb[i].ptr, mb[i].size); - consume_line(priv, priv->remainder, - priv->remainder_size + mb[i].size); - free(priv->remainder); - priv->remainder = NULL; - priv->remainder_size = 0; - } - return 0; -} - static void combine_diff(const unsigned char *parent, mmfile_t *result_file, struct sline *sline, int cnt, int n, int num_parent) { @@ -304,9 +268,10 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = 0; xecfg.flags = 0; - ecb.outf = combine_diff_outf; + ecb.outf = xdiff_outf; ecb.priv = &state; memset(&state, 0, sizeof(state)); + state.xm.consume = consume_line; state.nmask = nmask; state.sline = sline; state.lno = 1; @@ -314,9 +279,6 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, state.n = n; xdl_diff(&parent_file, result_file, &xpp, &xecfg, &ecb); - if (state.remainder && state.remainder_size) - consume_line(&state, state.remainder, state.remainder_size); - free(state.remainder); free(parent_file.ptr); /* Assign line numbers for this parent. diff --git a/xdiff-interface.c b/xdiff-interface.c new file mode 100644 index 0000000000..0a66ded953 --- /dev/null +++ b/xdiff-interface.c @@ -0,0 +1,58 @@ +#include "cache.h" +#include "xdiff-interface.h" + +static void consume_one(void *priv_, char *s, unsigned long size) +{ + struct xdiff_emit_state *priv = priv_; + char *ep; + while (size) { + unsigned long this_size; + ep = memchr(s, '\n', size); + this_size = (ep == NULL) ? size : (ep - s + 1); + priv->consume(priv, s, this_size); + size -= this_size; + s += this_size; + } +} + +int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) +{ + struct xdiff_emit_state *priv = priv_; + int i; + + for (i = 0; i < nbuf; i++) { + if (mb[i].ptr[mb[i].size-1] != '\n') { + /* Incomplete line */ + priv->remainder = realloc(priv->remainder, + priv->remainder_size + + mb[i].size); + memcpy(priv->remainder + priv->remainder_size, + mb[i].ptr, mb[i].size); + priv->remainder_size += mb[i].size; + continue; + } + + /* we have a complete line */ + if (!priv->remainder) { + consume_one(priv, mb[i].ptr, mb[i].size); + continue; + } + priv->remainder = realloc(priv->remainder, + priv->remainder_size + + mb[i].size); + memcpy(priv->remainder + priv->remainder_size, + mb[i].ptr, mb[i].size); + consume_one(priv, priv->remainder, + priv->remainder_size + mb[i].size); + free(priv->remainder); + priv->remainder = NULL; + priv->remainder_size = 0; + } + if (priv->remainder) { + consume_one(priv, priv->remainder, priv->remainder_size); + free(priv->remainder); + priv->remainder = NULL; + priv->remainder_size = 0; + } + return 0; +} diff --git a/xdiff-interface.h b/xdiff-interface.h new file mode 100644 index 0000000000..e2f0d66123 --- /dev/null +++ b/xdiff-interface.h @@ -0,0 +1,18 @@ +#ifndef XDIFF_INTERFACE_H +#define XDIFF_INTERFACE_H + +#include "xdiff/xdiff.h" + +struct xdiff_emit_state; + +typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long); + +struct xdiff_emit_state { + xdiff_emit_consume_fn consume; + char *remainder; + unsigned long remainder_size; +}; + +int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf); + +#endif From 7d6c447145c07bb7d96a9aa17e33838fbe76e405 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 5 Apr 2006 02:06:49 -0700 Subject: [PATCH 3/4] diff_flush(): leakfix. We were leaking filepairs when output-format was set to NO_OUTPUT. Signed-off-by: Junio C Hamano --- diff.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/diff.c b/diff.c index 890bdaa6b8..fa1613c2f1 100644 --- a/diff.c +++ b/diff.c @@ -1225,28 +1225,34 @@ void diff_flush(struct diff_options *options) for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; - if ((diff_output_format == DIFF_FORMAT_NO_OUTPUT) || - (p->status == DIFF_STATUS_UNKNOWN)) - continue; - if (p->status == 0) + + switch (p->status) { + case DIFF_STATUS_UNKNOWN: + break; + case 0: die("internal error in diff-resolve-rename-copy"); - switch (diff_output_format) { - case DIFF_FORMAT_PATCH: - diff_flush_patch(p, options); - break; - case DIFF_FORMAT_RAW: - case DIFF_FORMAT_NAME_STATUS: - diff_flush_raw(p, line_termination, - inter_name_termination, - options); - break; - case DIFF_FORMAT_NAME: - diff_flush_name(p, - inter_name_termination, - line_termination); break; + default: + switch (diff_output_format) { + case DIFF_FORMAT_PATCH: + diff_flush_patch(p, options); + break; + case DIFF_FORMAT_RAW: + case DIFF_FORMAT_NAME_STATUS: + diff_flush_raw(p, line_termination, + inter_name_termination, + options); + break; + case DIFF_FORMAT_NAME: + diff_flush_name(p, + inter_name_termination, + line_termination); + break; + case DIFF_FORMAT_NO_OUTPUT: + break; + } } - diff_free_filepair(q->queue[i]); + diff_free_filepair(p); } free(q->queue); q->queue = NULL; From c3b831bd84320374834f9984c118cb4fc7050ebc Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Wed, 5 Apr 2006 02:00:48 -0400 Subject: [PATCH 4/4] Add git-clean command This command removes untracked files from the working tree. This implementation is based on cg-clean with some simplifications. The documentation is included. [jc: with trivial documentation fix, noticed by Jakub Narebski] Signed-off-by: Pavel Roskin Signed-off-by: Junio C Hamano --- .gitignore | 1 + Documentation/git-clean.txt | 50 +++++++++++++++++++++++ Makefile | 2 +- git-clean.sh | 80 +++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 Documentation/git-clean.txt create mode 100755 git-clean.sh diff --git a/.gitignore b/.gitignore index 75891c393b..b5959d6311 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ git-checkout git-checkout-index git-cherry git-cherry-pick +git-clean git-clone git-clone-pack git-commit diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt new file mode 100644 index 0000000000..36890c543d --- /dev/null +++ b/Documentation/git-clean.txt @@ -0,0 +1,50 @@ +git-clean(1) +============ + +NAME +---- +git-clean - Remove untracked files from the working tree + +SYNOPSIS +-------- +[verse] +'git-clean' [-d] [-n] [-q] [-x | -X] + +DESCRIPTION +----------- +Removes files unknown to git. This allows to clean the working tree +from files that are not under version control. If the '-x' option is +specified, ignored files are also removed, allowing to remove all +build products. + +OPTIONS +------- +-d:: + Remove untracked directories in addition to untracked files. + +-n:: + Don't actually remove anything, just show what would be done. + +-q:: + Be quiet, only report errors, but not the files that are + successfully removed. + +-x:: + Don't use the ignore rules. This allows removing all untracked + files, including build products. This can be used (possibly in + conjunction with gitlink:git-reset[1]) to create a pristine + working directory to test a clean build. + +-X:: + Remove only files ignored by git. This may be useful to rebuild + everything from scratch, but keep manually created files. + + +Author +------ +Written by Pavel Roskin + + +GIT +--- +Part of the gitlink:git[7] suite diff --git a/Makefile b/Makefile index 145099adaa..3367b8c13d 100644 --- a/Makefile +++ b/Makefile @@ -114,7 +114,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ SCRIPT_SH = \ git-add.sh git-bisect.sh git-branch.sh git-checkout.sh \ - git-cherry.sh git-clone.sh git-commit.sh \ + git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \ git-count-objects.sh git-diff.sh git-fetch.sh \ git-format-patch.sh git-log.sh git-ls-remote.sh \ git-merge-one-file.sh git-parse-remote.sh \ diff --git a/git-clean.sh b/git-clean.sh new file mode 100755 index 0000000000..b200868e60 --- /dev/null +++ b/git-clean.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# +# Copyright (c) 2005-2006 Pavel Roskin +# + +USAGE="[-d] [-n] [-q] [-x | -X]" +LONG_USAGE='Clean untracked files from the working directory + -d remove directories as well + -n don'\''t remove anything, just show what would be done + -q be quiet, only report errors + -x remove ignored files as well + -X remove only ignored files as well' +SUBDIRECTORY_OK=Yes +. git-sh-setup + +ignored= +ignoredonly= +cleandir= +quiet= +rmf="rm -f" +rmrf="rm -rf" +rm_refuse="echo Not removing" +echo1="echo" + +while case "$#" in 0) break ;; esac +do + case "$1" in + -d) + cleandir=1 + ;; + -n) + quiet=1 + rmf="echo Would remove" + rmrf="echo Would remove" + rm_refuse="echo Would not remove" + echo1=":" + ;; + -q) + quiet=1 + ;; + -x) + ignored=1 + ;; + -X) + ignoredonly=1 + ;; + *) + usage + esac + shift +done + +case "$ignored,$ignoredonly" in + 1,1) usage;; +esac + +if [ -z "$ignored" ]; then + excl="--exclude-per-directory=.gitignore" + if [ -f "$GIT_DIR/info/exclude" ]; then + excl_info="--exclude-from=$GIT_DIR/info/exclude" + fi + if [ "$ignoredonly" ]; then + excl="$excl --ignored" + fi +fi + +git-ls-files --others --directory $excl ${excl_info:+"$excl_info"} | +while read -r file; do + if [ -d "$file" -a ! -L "$file" ]; then + if [ -z "$cleandir" ]; then + $rm_refuse "$file" + continue + fi + $echo1 "Removing $file" + $rmrf "$file" + else + $echo1 "Removing $file" + $rmf "$file" + fi +done