From: Junio C Hamano Date: Sun, 6 Jul 2008 01:33:16 +0000 (-0700) Subject: Merge branch 'qq/maint' X-Git-Tag: v1.6.0-rc0~135 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/08b51f51e6a4cf2f5ad4b893707f1337a450e499?ds=inline;hp=-c Merge branch 'qq/maint' * qq/maint: clone -q: honor "quiet" option over native transports. attribute documentation: keep EXAMPLE at end builtin-commit.c: Use 'git_config_string' to get 'commit.template' http.c: Use 'git_config_string' to clean up SSL config. diff.c: Use 'git_config_string' to get 'diff.external' convert.c: Use 'git_config_string' to get 'smudge' and 'clean' builtin-log.c: Use 'git_config_string' to get 'format.subjectprefix' and 'format.suffix' Documentation cvs: Clarify when a bare repository is needed Documentation: be precise about which date --pretty uses Conflicts: Documentation/gitattributes.txt --- 08b51f51e6a4cf2f5ad4b893707f1337a450e499 diff --combined Documentation/git-cvsimport.txt index 1614e8df89,93b7d2dc99..b7a8c10b87 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@@ -9,7 -9,7 +9,7 @@@ git-cvsimport - Salvage your data out o SYNOPSIS -------- [verse] -'git-cvsimport' [-o ] [-h] [-v] [-d ] +'git cvsimport' [-o ] [-h] [-v] [-d ] [-A ] [-p ] [-P ] [-C ] [-z ] [-i] [-k] [-u] [-s ] [-a] [-m] [-M ] [-S ] [-L ] @@@ -25,12 -25,18 +25,18 @@@ Splitting the CVS log into patch sets i At least version 2.1 is required. You should *never* do any work of your own on the branches that are -created by git-cvsimport. By default initial import will create and populate a +created by 'git-cvsimport'. By default initial import will create and populate a "master" branch from the CVS repository's main branch which you're free -to work with; after that, you need to 'git merge' incremental imports, or +to work with; after that, you need to 'git-merge' incremental imports, or any CVS branches, yourself. It is advisable to specify a named remote via -r to separate and protect the incoming branches. + If you intend to set up a shared public repository that all developers can + read/write, or if you want to use linkgit:git-cvsserver[1], then you + probably want to make a bare clone of the imported repository, + and use the clone as the shared repository. + See linkgit:gitcvs-migration[7]. + OPTIONS ------- @@@ -40,13 -46,13 +46,13 @@@ -d :: The root of the CVS archive. May be local (a simple path) or remote; currently, only the :local:, :ext: and :pserver: access methods - are supported. If not given, git-cvsimport will try to read it + are supported. If not given, 'git-cvsimport' will try to read it from `CVS/Root`. If no such file exists, it checks for the `CVSROOT` environment variable. :: The CVS module you want to import. Relative to . - If not given, git-cvsimport tries to read it from + If not given, 'git-cvsimport' tries to read it from `CVS/Repository`. -C :: @@@ -56,14 -62,14 +62,14 @@@ -r :: The git remote to import this CVS repository into. Moves all CVS branches into remotes// - akin to the git-clone --use-separate-remote option. + akin to the 'git-clone' "--use-separate-remote" option. -o :: When no remote is specified (via -r) the 'HEAD' branch from CVS is imported to the 'origin' branch within the git repository, as 'HEAD' already has a special meaning for git. When a remote is specified the 'HEAD' branch is named - remotes//master mirroring git-clone behaviour. + remotes//master mirroring 'git-clone' behaviour. Use this option if you want to import into a different branch. + @@@ -136,17 -142,17 +142,17 @@@ This option can be used several times t --------- + -git-cvsimport will make it appear as those authors had +'git-cvsimport' will make it appear as those authors had their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly all along. + For convenience, this data is saved to `$GIT_DIR/cvs-authors` each time the '-A' option is provided and read from that same -file each time git-cvsimport is run. +file each time 'git-cvsimport' is run. + It is not recommended to use this feature if you intend to export changes back to CVS again later with -linkgit:git-cvsexportcommit[1]. +'git-cvsexportcommit'. -h:: Print a short usage message and exit. diff --combined Documentation/git-cvsserver.txt index 2aacdc628f,19da87e71d..c2d3c90d27 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@@ -22,7 -22,7 +22,7 @@@ cvspserver stream tcp nowait nobody /us Usage: [verse] -'git-cvsserver' [options] [pserver|server] [ ...] +'git cvsserver' [options] [pserver|server] [ ...] OPTIONS ------- @@@ -77,7 -77,7 +77,7 @@@ over pserver for anonymous CVS access CVS clients cannot tag, branch or perform GIT merges. -git-cvsserver maps GIT branches to CVS modules. This is very different +'git-cvsserver' maps GIT branches to CVS modules. This is very different from what most CVS users would expect since in CVS modules usually represent one or more directories. @@@ -103,7 -103,7 +103,7 @@@ looks lik ------ No special setup is needed for SSH access, other than having GIT tools in the PATH. If you have clients that do not accept the CVS_SERVER -environment variable, you can rename git-cvsserver to cvs. +environment variable, you can rename 'git-cvsserver' to `cvs`. Note: Newer CVS versions (>= 1.12.11) also support specifying CVS_SERVER directly in CVSROOT like @@@ -113,9 -113,9 +113,9 @@@ cvs -d ":ext;CVS_SERVER=git-cvsserver:u ------ This has the advantage that it will be saved in your 'CVS/Root' files and you don't need to worry about always setting the correct environment -variable. SSH users restricted to git-shell don't need to override the default -with CVS_SERVER (and shouldn't) as git-shell understands `cvs` to mean -git-cvsserver and pretends that the other end runs the real cvs better. +variable. SSH users restricted to 'git-shell' don't need to override the default +with CVS_SERVER (and shouldn't) as 'git-shell' understands `cvs` to mean +'git-cvsserver' and pretends that the other end runs the real 'cvs' better. -- 2. For each repo that you want accessible from CVS you need to edit config in the repo and add the following section. @@@ -128,11 -128,14 +128,14 @@@ logfile=/path/to/logfile ------ -Note: you need to ensure each user that is going to invoke git-cvsserver has +Note: you need to ensure each user that is going to invoke 'git-cvsserver' has write access to the log file and to the database (see <>. If you want to offer write access over SSH, the users of course also need write access to the git repository itself. + You also need to ensure that each repository is "bare" (without a git index + file) for `cvs commit` to work. See linkgit:gitcvs-migration[7]. + [[configaccessmethod]] All configuration variables can also be overridden for a specific method of access. Valid method names are "ext" (for SSH access) and "pserver". The @@@ -150,7 -153,7 +153,7 @@@ allowing access over SSH automatically saving it in your 'CVS/Root' files, then you need to set them explicitly in your environment. CVSROOT should be set as per normal, but the directory should point at the appropriate git repo. As above, for SSH clients - _not_ restricted to git-shell, CVS_SERVER should be set to git-cvsserver. + _not_ restricted to 'git-shell', CVS_SERVER should be set to 'git-cvsserver'. + -- ------ @@@ -178,27 -181,27 +181,27 @@@ Database Backend ---------------- -git-cvsserver uses one database per git head (i.e. CVS module) to +'git-cvsserver' uses one database per git head (i.e. CVS module) to store information about the repository for faster access. The database doesn't contain any persistent data and can be completely regenerated from the git repository at any time. The database needs to be updated (i.e. written to) after every commit. -If the commit is done directly by using git (as opposed to -using git-cvsserver) the update will need to happen on the -next repository access by git-cvsserver, independent of +If the commit is done directly by using `git` (as opposed to +using 'git-cvsserver') the update will need to happen on the +next repository access by 'git-cvsserver', independent of access method and requested operation. That means that even if you offer only read access (e.g. by using -the pserver method), git-cvsserver should have write access to +the pserver method), 'git-cvsserver' should have write access to the database to work reliably (otherwise you need to make sure -that the database is up-to-date any time git-cvsserver is executed). +that the database is up-to-date any time 'git-cvsserver' is executed). By default it uses SQLite databases in the git directory, named `gitcvs..sqlite`. Note that the SQLite backend creates temporary files in the same directory as the database file on write so it might not be enough to grant the users using -git-cvsserver write access to the database file without granting +'git-cvsserver' write access to the database file without granting them write access to the directory, too. You can configure the database backend with the following @@@ -207,7 -210,7 +210,7 @@@ configuration variables Configuring database backend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -git-cvsserver uses the Perl DBI module. Please also read +'git-cvsserver' uses the Perl DBI module. Please also read its documentation if changing these variables, especially about `DBI->connect()`. @@@ -259,7 -262,7 +262,7 @@@ In `dbdriver` and `dbuser` you can use %a:: access method (one of "ext" or "pserver") %u:: - Name of the user running git-cvsserver. + Name of the user running 'git-cvsserver'. If no name can be determined, the numeric uid is used. @@@ -285,8 -288,8 +288,8 @@@ you will definitely want to have SSH ke Alternatively, you can just use the non-standard extssh protocol that Eclipse offer. In that case CVS_SERVER is ignored, and you will have to replace -the cvs utility on the server with git-cvsserver or manipulate your `.bashrc` -so that calling 'cvs' effectively calls git-cvsserver. +the cvs utility on the server with 'git-cvsserver' or manipulate your `.bashrc` +so that calling 'cvs' effectively calls 'git-cvsserver'. Clients known to work --------------------- @@@ -328,13 -331,14 +331,13 @@@ is left blank. But if `gitcvs.allbinary the correct '-k' mode will be guessed based on the contents of the file. -For best consistency with cvs, it is probably best to override the +For best consistency with 'cvs', it is probably best to override the defaults by setting `gitcvs.usecrlfattr` to true, and `gitcvs.allbinary` to "guess". Dependencies ------------ - -git-cvsserver depends on DBD::SQLite. +'git-cvsserver' depends on DBD::SQLite. Copyright and Authors --------------------- diff --combined Documentation/gitattributes.txt index 6a246eb1fc,ef06d94ca8..d7b41142d2 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@@ -87,9 -87,9 +87,9 @@@ Checking-out and checking-i These attributes affect how the contents stored in the repository are copied to the working tree files when commands -such as `git checkout` and `git merge` run. They also affect how +such as 'git-checkout' and 'git-merge' run. They also affect how git stores the contents you prepare in the working tree in the -repository upon `git add` and `git commit`. +repository upon 'git-add' and 'git-commit'. `crlf` ^^^^^^ @@@ -148,16 -148,16 +148,16 @@@ an irreversible conversion. The safet a conversion done to the files in the work tree, but there are a few exceptions. Even though... -- "git add" itself does not touch the files in the work tree, the +- 'git-add' itself does not touch the files in the work tree, the next checkout would, so the safety triggers; -- "git apply" to update a text file with a patch does touch the files +- 'git-apply' to update a text file with a patch does touch the files in the work tree, but the operation is about text files and CRLF conversion is about fixing the line ending inconsistencies, so the safety does not trigger; -- "git diff" itself does not touch the files in the work tree, it is - often run to inspect the changes you intend to next "git add". To +- 'git-diff' itself does not touch the files in the work tree, it is + often run to inspect the changes you intend to next 'git-add'. To catch potential problems early, safety triggers. @@@ -214,7 -214,7 +214,7 @@@ with `crlf`, and then `ident` and fed t Generating diff text ~~~~~~~~~~~~~~~~~~~~ -The attribute `diff` affects if `git diff` generates textual +The attribute `diff` affects if 'git-diff' generates textual patch for the path or just says `Binary files differ`. It also can affect what line is shown on the hunk header `@@ -k,l +n,m @@` line. @@@ -278,7 -278,7 +278,7 @@@ is prefixed with a line of the form The text is called 'hunk header', and by default a line that begins with an alphabet, an underscore or a dollar sign is used, -which matches what GNU `diff -p` output uses. This default +which matches what GNU 'diff -p' output uses. This default selection however is not suited for some contents, and you can use customized pattern to make a selection. @@@ -322,7 -322,7 +322,7 @@@ and other programs such as `git revert Set:: Built-in 3-way merge driver is used to merge the - contents in a way similar to `merge` command of `RCS` + contents in a way similar to 'merge' command of `RCS` suite. This is suitable for ordinary text files. Unset:: @@@ -426,7 -426,7 +426,7 @@@ Checking whitespace error ^^^^^^^^^^^^ The `core.whitespace` configuration variable allows you to define what -`diff` and `apply` should consider whitespace errors for all paths in +'diff' and 'apply' should consider whitespace errors for all paths in the project (See linkgit:git-config[1]). This attribute gives you finer control per path. @@@ -450,6 -450,23 +450,29 @@@ String: variable. + Creating an archive + ~~~~~~~~~~~~~~~~~~~ + ++`export-ignore` ++^^^^^^^^^^^^^^^ ++ ++Files and directories with the attribute `export-ignore` won't be added to ++archive files. ++ + `export-subst` + ^^^^^^^^^^^^^^ + + If the attribute `export-subst` is set for a file then git will expand + several placeholders when adding this file to an archive. The -expansion depends on the availability of a commit ID, i.e. if ++expansion depends on the availability of a commit ID, i.e., if + linkgit:git-archive[1] has been given a tree instead of a commit or a + tag then no replacement will be done. The placeholders are the same + as those for the option `--pretty=format:` of linkgit:git-log[1], + except that they need to be wrapped like this: `$Format:PLACEHOLDERS$` + in the file. E.g. the string `$Format:%H$` will be replaced by the + commit hash. + + EXAMPLE ------- @@@ -499,28 -516,6 +522,6 @@@ frotz unspecifie ---------------------------------------------------------------- - Creating an archive - ~~~~~~~~~~~~~~~~~~~ - - `export-ignore` - ^^^^^^^^^^^^^^^ - - Files and directories with the attribute `export-ignore` won't be added to - archive files. - - `export-subst` - ^^^^^^^^^^^^^^ - - If the attribute `export-subst` is set for a file then git will expand - several placeholders when adding this file to an archive. The - expansion depends on the availability of a commit ID, i.e., if - 'git-archive' has been given a tree instead of a commit or a - tag then no replacement will be done. The placeholders are the same - as those for the option `--pretty=format:` of linkgit:git-log[1], - except that they need to be wrapped like this: `$Format:PLACEHOLDERS$` - in the file. E.g. the string `$Format:%H$` will be replaced by the - commit hash. - GIT --- diff --combined Documentation/gitcvs-migration.txt index 2eb6972a93,0325d6759d..aaa7ef737a --- a/Documentation/gitcvs-migration.txt +++ b/Documentation/gitcvs-migration.txt @@@ -18,9 -18,9 +18,9 @@@ important than any other. However, yo designating a single shared repository which people can synchronize with; this document explains how to do that. -Some basic familiarity with git is required. This -linkgit:gittutorial[7][tutorial introduction to git] and the -linkgit:gitglossary[7][git glossary] should be sufficient. +Some basic familiarity with git is required. Having gone through +linkgit:gittutorial[7] and +linkgit:gitglossary[7] should be sufficient. Developing against a shared repository -------------------------------------- @@@ -34,7 -34,7 +34,7 @@@ $ git clone foo.com:/pub/repo.git/ my-p $ cd my-project ------------------------------------------------ -and hack away. The equivalent of `cvs update` is +and hack away. The equivalent of 'cvs update' is ------------------------------------------------ $ git pull origin @@@ -46,28 -46,28 +46,28 @@@ them first before running git pull [NOTE] ================================ -The `pull` command knows where to get updates from because of certain -configuration variables that were set by the first `git clone` +The 'pull' command knows where to get updates from because of certain +configuration variables that were set by the first 'git-clone' command; see `git config -l` and the linkgit:git-config[1] man page for details. ================================ You can update the shared repository with your changes by first committing -your changes, and then using the linkgit:git-push[1] command: +your changes, and then using the 'git-push' command: ------------------------------------------------ $ git push origin master ------------------------------------------------ to "push" those commits to the shared repository. If someone else has -updated the repository more recently, `git push`, like `cvs commit`, will +updated the repository more recently, 'git-push', like 'cvs commit', will complain, in which case you must pull any changes before attempting the push again. -In the `git push` command above we specify the name of the remote branch -to update (`master`). If we leave that out, `git push` tries to update +In the 'git-push' command above we specify the name of the remote branch +to update (`master`). If we leave that out, 'git-push' tries to update any branches in the remote repository that have the same name as a branch -in the local repository. So the last `push` can be done with either of: +in the local repository. So the last 'push' can be done with either of: ------------ $ git push origin @@@ -81,8 -81,8 +81,8 @@@ Setting Up a Shared Repositor ------------------------------ We assume you have already created a git repository for your project, -possibly created from scratch or from a tarball (see the -linkgit:gittutorial[7][tutorial]), or imported from an already existing CVS +possibly created from scratch or from a tarball (see +linkgit:gittutorial[7]), or imported from an already existing CVS repository (see the next section). Assume your existing repo is at /home/alice/myproject. Create a new "bare" @@@ -118,7 -118,7 +118,7 @@@ Importing a CVS archiv First, install version 2.1 or higher of cvsps from link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make sure it is in your path. Then cd to a checked out CVS working directory -of the project you are interested in and run linkgit:git-cvsimport[1]: +of the project you are interested in and run 'git-cvsimport': ------------------------------------------- $ git cvsimport -C @@@ -143,12 -143,17 +143,17 @@@ work, you must not modify the imported branches for your own changes, and merge in the imported branches as necessary. + If you want a shared repository, you will need to make a bare clone + of the imported directory, as described above. Then treat the imported + directory as another development clone for purposes of merging + incremental imports. + Advanced Shared Repository Management ------------------------------------- Git allows you to specify scripts called "hooks" to be run at certain points. You can use these, for example, to send all commits to the shared -repository to a mailing list. See linkgit:githooks[5][Hooks used by git]. +repository to a mailing list. See linkgit:githooks[5]. You can enforce finer grained permissions using update hooks. See link:howto/update-hook-example.txt[Controlling access to branches using diff --combined builtin-commit.c index e3ad38b3bd,bcbea3893b..745c11e773 --- a/builtin-commit.c +++ b/builtin-commit.c @@@ -45,12 -45,12 +45,13 @@@ static enum COMMIT_PARTIAL, } commit_style; - static char *logfile, *force_author, *template_file; + static char *logfile, *force_author; + static const char *template_file; static char *edit_message, *use_message; static char *author_name, *author_email, *author_date; static int all, edit_flag, also, interactive, only, amend, signoff; -static int quiet, verbose, untracked_files, no_verify, allow_empty; +static int quiet, verbose, no_verify, allow_empty; +static char *untracked_files_arg; /* * The default commit message cleanup mode will remove the lines * beginning with # (shell comments) and leading and trailing @@@ -103,7 -103,7 +104,7 @@@ static struct option builtin_commit_opt OPT_BOOLEAN('o', "only", &only, "commit only specified files"), OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"), OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"), - OPT_BOOLEAN('u', "untracked-files", &untracked_files, "show all untracked files"), + { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"), OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"), @@@ -348,7 -348,7 +349,7 @@@ static int run_status(FILE *fp, const c s.reference = "HEAD^1"; } s.verbose = verbose; - s.untracked = untracked_files; + s.untracked = (show_untracked_files == SHOW_ALL_UNTRACKED_FILES); s.index_file = index_file; s.fp = fp; s.nowarn = nowarn; @@@ -503,8 -503,7 +504,8 @@@ static int prepare_to_commit(const cha fp = fopen(git_path(commit_editmsg), "w"); if (fp == NULL) - die("could not open %s", git_path(commit_editmsg)); + die("could not open %s: %s", + git_path(commit_editmsg), strerror(errno)); if (cleanup_mode != CLEANUP_NONE) stripspace(&sb, 0); @@@ -797,17 -796,6 +798,17 @@@ static int parse_and_validate_options(i else die("Invalid cleanup mode %s", cleanup_arg); + if (!untracked_files_arg) + ; /* default already initialized */ + else if (!strcmp(untracked_files_arg, "no")) + show_untracked_files = SHOW_NO_UNTRACKED_FILES; + else if (!strcmp(untracked_files_arg, "normal")) + show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; + else if (!strcmp(untracked_files_arg, "all")) + show_untracked_files = SHOW_ALL_UNTRACKED_FILES; + else + die("Invalid untracked files mode '%s'", untracked_files_arg); + if (all && argc > 0) die("Paths with -a does not make sense."); else if (interactive && argc > 0) @@@ -877,12 -865,8 +878,8 @@@ static void print_summary(const char *p int git_commit_config(const char *k, const char *v, void *cb) { - if (!strcmp(k, "commit.template")) { - if (!v) - return config_error_nonbool(v); - template_file = xstrdup(v); - return 0; - } + if (!strcmp(k, "commit.template")) + return git_config_string(&template_file, k, v); return git_status_config(k, v, cb); } diff --combined diff.c index 803fbba451,78c4d3a35a..6a39b393f3 --- a/diff.c +++ b/diff.c @@@ -153,12 -153,8 +153,8 @@@ int git_diff_ui_config(const char *var diff_auto_refresh_index = git_config_bool(var, value); return 0; } - if (!strcmp(var, "diff.external")) { - if (!value) - return config_error_nonbool(var); - external_diff_cmd_cfg = xstrdup(value); - return 0; - } + if (!strcmp(var, "diff.external")) + return git_config_string(&external_diff_cmd_cfg, var, value); if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); @@@ -535,9 -531,9 +531,9 @@@ static void emit_add_line(const char *r else { /* Emit just the prefix, then the rest. */ emit_line(ecbdata->file, set, reset, line, ecbdata->nparents); - (void)check_and_emit_line(line + ecbdata->nparents, - len - ecbdata->nparents, ecbdata->ws_rule, - ecbdata->file, set, reset, ws); + ws_check_emit(line + ecbdata->nparents, + len - ecbdata->nparents, ecbdata->ws_rule, + ecbdata->file, set, reset, ws); } } @@@ -830,12 -826,12 +826,12 @@@ static void show_stats(struct diffstat_ /* Sanity: give at least 5 columns to the graph, * but leave at least 10 columns for the name. */ - if (width < name_width + 15) { - if (name_width <= 25) - width = name_width + 15; - else - name_width = width - 15; - } + if (width < 25) + width = 25; + if (name_width < 10) + name_width = 10; + else if (width < name_width + 15) + name_width = width - 15; /* Find the longest filename and max number of changes */ reset = diff_get_color_opt(options, DIFF_RESET); @@@ -928,8 -924,7 +924,8 @@@ total = add + del; } show_name(options->file, prefix, name, len, reset, set); - fprintf(options->file, "%5d ", added + deleted); + fprintf(options->file, "%5d%s", added + deleted, + added + deleted ? " " : ""); show_graph(options->file, '+', add, add_c, reset); show_graph(options->file, '-', del, del_c, reset); fprintf(options->file, "\n"); @@@ -1136,85 -1131,42 +1132,85 @@@ static void free_diffstat_info(struct d struct checkdiff_t { struct xdiff_emit_state xm; const char *filename; - int lineno, color_diff; + int lineno; + struct diff_options *o; unsigned ws_rule; unsigned status; - FILE *file; + int trailing_blanks_start; }; +static int is_conflict_marker(const char *line, unsigned long len) +{ + char firstchar; + int cnt; + + if (len < 8) + return 0; + firstchar = line[0]; + switch (firstchar) { + case '=': case '>': case '<': + break; + default: + return 0; + } + for (cnt = 1; cnt < 7; cnt++) + if (line[cnt] != firstchar) + return 0; + /* line[0] thru line[6] are same as firstchar */ + if (firstchar == '=') { + /* divider between ours and theirs? */ + if (len != 8 || line[7] != '\n') + return 0; + } else if (len < 8 || !isspace(line[7])) { + /* not divider before ours nor after theirs */ + return 0; + } + return 1; +} + static void checkdiff_consume(void *priv, char *line, unsigned long len) { struct checkdiff_t *data = priv; - const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE); - const char *reset = diff_get_color(data->color_diff, DIFF_RESET); - const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW); + int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF); + const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE); + const char *reset = diff_get_color(color_diff, DIFF_RESET); + const char *set = diff_get_color(color_diff, DIFF_FILE_NEW); char *err; if (line[0] == '+') { unsigned bad; data->lineno++; - bad = check_and_emit_line(line + 1, len - 1, - data->ws_rule, NULL, NULL, NULL, NULL); + if (!ws_blank_line(line + 1, len - 1, data->ws_rule)) + data->trailing_blanks_start = 0; + else if (!data->trailing_blanks_start) + data->trailing_blanks_start = data->lineno; + if (is_conflict_marker(line + 1, len - 1)) { + data->status |= 1; + fprintf(data->o->file, + "%s:%d: leftover conflict marker\n", + data->filename, data->lineno); + } + bad = ws_check(line + 1, len - 1, data->ws_rule); if (!bad) return; data->status |= bad; err = whitespace_error_string(bad); - fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err); + fprintf(data->o->file, "%s:%d: %s.\n", + data->filename, data->lineno, err); free(err); - emit_line(data->file, set, reset, line, 1); - (void)check_and_emit_line(line + 1, len - 1, data->ws_rule, - data->file, set, reset, ws); - } else if (line[0] == ' ') + emit_line(data->o->file, set, reset, line, 1); + ws_check_emit(line + 1, len - 1, data->ws_rule, + data->o->file, set, reset, ws); + } else if (line[0] == ' ') { data->lineno++; - else if (line[0] == '@') { + data->trailing_blanks_start = 0; + } else if (line[0] == '@') { char *plus = strchr(line, '+'); if (plus) data->lineno = strtol(plus, NULL, 10) - 1; else die("invalid diff"); + data->trailing_blanks_start = 0; } } @@@ -1587,9 -1539,8 +1583,9 @@@ static void builtin_diffstat(const cha static void builtin_checkdiff(const char *name_a, const char *name_b, const char *attr_path, - struct diff_filespec *one, - struct diff_filespec *two, struct diff_options *o) + struct diff_filespec *one, + struct diff_filespec *two, + struct diff_options *o) { mmfile_t mf1, mf2; struct checkdiff_t data; @@@ -1601,18 -1552,13 +1597,18 @@@ data.xm.consume = checkdiff_consume; data.filename = name_b ? name_b : name_a; data.lineno = 0; - data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); + data.o = o; data.ws_rule = whitespace_rule(attr_path); - data.file = o->file; if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); + /* + * All the other codepaths check both sides, but not checking + * the "old" side here is deliberate. We are checking the newly + * introduced changes, and as long as the "new" side is text, we + * can and should check what it introduces. + */ if (diff_filespec_is_binary(two)) goto free_and_return; else { @@@ -1626,12 -1572,6 +1622,12 @@@ ecb.outf = xdiff_outf; ecb.priv = &data; xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + + if (data.trailing_blanks_start) { + fprintf(o->file, "%s:%d: ends with blank lines.\n", + data.filename, data.trailing_blanks_start); + data.status = 1; /* report errors */ + } } free_and_return: diff_free_filespec_data(one); diff --combined transport.c index 4145eed979,6f549b336b..6eb65b873a --- a/transport.c +++ b/transport.c @@@ -645,7 -645,9 +645,9 @@@ static int fetch_refs_via_pack(struct t args.lock_pack = 1; args.use_thin_pack = data->thin; args.include_tag = data->followtags; - args.verbose = transport->verbose > 0; + args.verbose = (transport->verbose > 0); + args.quiet = args.no_progress = (transport->verbose < 0); + args.no_progress = !isatty(1); args.depth = data->depth; for (i = 0; i < nr_heads; i++) @@@ -709,8 -711,7 +711,8 @@@ static int is_local(const char *url { const char *colon = strchr(url, ':'); const char *slash = strchr(url, '/'); - return !colon || (slash && slash < colon); + return !colon || (slash && slash < colon) || + has_dos_drive_prefix(url); } static int is_file(const char *url)