Commit a1a9d0bd by Vicent Marti

Merge pull request #2066 from libgit2/rb/builtin-diff-drivers

Add built in diff drivers
parents 93954245 daebb598
......@@ -39,27 +39,34 @@
# but has otherwise not contributed to git.)
#
ok Adam Simpkins <adam@adamsimpkins.net> (http transport)
ok Adrian Johnson <ajohnson@redneon.com>
ok Alexey Shumkin <alex.crezoff@gmail.com>
ok Andreas Ericsson <ae@op5.se>
ok Boyd Lynn Gerber <gerberb@zenez.com>
ok Brandon Casey <drafnel@gmail.com>
ok Brian Downing <bdowning@lavos.net>
ok Brian Gernhardt <benji@silverinsanity.com>
ok Christian Couder <chriscool@tuxfamily.org>
ok Daniel Barkalow <barkalow@iabervon.org>
ok Florian Forster <octo@verplant.org>
ok Gustaf Hendeby <hendeby@isy.liu.se>
ok Holger Weiss <holger@zedat.fu-berlin.de>
ok Jeff King <peff@peff.net>
ok Johannes Schindelin <Johannes.Schindelin@gmx.de>
ok Johannes Sixt <j6t@kdbg.org>
ask Jonathan Nieder <jrnieder@gmail.com>
ok Junio C Hamano <gitster@pobox.com>
ok Kristian Høgsberg <krh@redhat.com>
ok Linus Torvalds <torvalds@linux-foundation.org>
ok Lukas Sandström <lukass@etek.chalmers.se>
ok Matthieu Moy <Matthieu.Moy@imag.fr>
ok Michael Haggerty <mhagger@alum.mit.edu>
ign Mike McCormack <mike@codeweavers.com> (imap-send)
ok Nicolas Pitre <nico@fluxnic.net> <nico@cam.org>
ok Paolo Bonzini <bonzini@gnu.org>
ok Paul Kocher <paul@cryptography.com>
ok Peter Hagervall <hager@cs.umu.se>
ok Petr Onderka <gsvick@gmail.com>
ok Pierre Habouzit <madcoder@debian.org>
ok Pieter de Bie <pdebie@ai.rug.nl>
ok René Scharfe <rene.scharfe@lsrfire.ath.cx>
......@@ -68,4 +75,5 @@ ok Sebastian Schuberth <sschuberth@gmail.com>
ok Shawn O. Pearce <spearce@spearce.org>
ok Steffen Prohaska <prohaska@zib.de>
ok Sven Verdoolaege <skimo@kotnet.org>
ask Thomas Rast <tr@thomasrast.ch> (ok before 6-Oct-2013)
ok Torsten Bögershausen <tboegi@web.de>
......@@ -26,10 +26,13 @@ typedef enum {
DIFF_DRIVER_PATTERNLIST = 3,
} git_diff_driver_t;
typedef struct {
regex_t re;
int flags;
} git_diff_driver_pattern;
enum {
DIFF_CONTEXT_FIND_NORMAL = 0,
DIFF_CONTEXT_FIND_ICASE = (1 << 0),
DIFF_CONTEXT_FIND_EXT = (1 << 1),
REG_NEGATE = (1 << 15) /* get out of the way of existing flags */
};
/* data for finding function context for a given file type */
......@@ -37,11 +40,13 @@ struct git_diff_driver {
git_diff_driver_t type;
uint32_t binary_flags;
uint32_t other_flags;
git_array_t(regex_t) fn_patterns;
git_array_t(git_diff_driver_pattern) fn_patterns;
regex_t word_pattern;
char name[GIT_FLEX_ARRAY];
};
#include "userdiff.h"
struct git_diff_driver_registry {
git_strmap *drivers;
};
......@@ -81,34 +86,59 @@ void git_diff_driver_registry_free(git_diff_driver_registry *reg)
git__free(reg);
}
static int diff_driver_add_funcname(
git_diff_driver *drv, const char *name, int regex_flags)
static int diff_driver_add_patterns(
git_diff_driver *drv, const char *regex_str, int regex_flags)
{
int error;
regex_t re, *re_ptr;
if ((error = regcomp(&re, name, regex_flags)) != 0) {
/* TODO: warning about bad regex instead of failure */
error = giterr_set_regex(&re, error);
regfree(&re);
return error;
int error = 0;
const char *scan, *end;
git_diff_driver_pattern *pat = NULL;
git_buf buf = GIT_BUF_INIT;
for (scan = regex_str; scan; scan = end) {
/* get pattern to fill in */
if ((pat = git_array_alloc(drv->fn_patterns)) == NULL) {
error = -1;
break;
}
pat->flags = regex_flags;
if (*scan == '!') {
pat->flags |= REG_NEGATE;
++scan;
}
if ((end = strchr(scan, '\n')) != NULL) {
error = git_buf_set(&buf, scan, end - scan);
end++;
} else {
error = git_buf_sets(&buf, scan);
}
if (error < 0)
break;
if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) < 0) {
/* if regex fails to compile, warn? fail? */
error = giterr_set_regex(&pat->re, error);
regfree(&pat->re);
break;
}
}
re_ptr = git_array_alloc(drv->fn_patterns);
GITERR_CHECK_ALLOC(re_ptr);
if (error && pat != NULL)
(void)git_array_pop(drv->fn_patterns); /* release last item */
git_buf_free(&buf);
memcpy(re_ptr, &re, sizeof(re));
return 0;
return error;
}
static int diff_driver_xfuncname(const git_config_entry *entry, void *payload)
{
return diff_driver_add_funcname(payload, entry->value, REG_EXTENDED);
return diff_driver_add_patterns(payload, entry->value, REG_EXTENDED);
}
static int diff_driver_funcname(const git_config_entry *entry, void *payload)
{
return diff_driver_add_funcname(payload, entry->value, 0);
return diff_driver_add_patterns(payload, entry->value, 0);
}
static git_diff_driver_registry *git_repository_driver_registry(
......@@ -128,12 +158,65 @@ static git_diff_driver_registry *git_repository_driver_registry(
return repo->diff_drivers;
}
static int git_diff_driver_builtin(
git_diff_driver **out,
git_diff_driver_registry *reg,
const char *driver_name)
{
int error = 0;
git_diff_driver_definition *ddef = NULL;
git_diff_driver *drv = NULL;
size_t namelen, idx;
for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) {
if (!strcasecmp(driver_name, builtin_defs[idx].name)) {
ddef = &builtin_defs[idx];
break;
}
}
if (!ddef)
goto done;
namelen = strlen(ddef->name);
drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
GITERR_CHECK_ALLOC(drv);
drv->type = DIFF_DRIVER_PATTERNLIST;
memcpy(drv->name, ddef->name, namelen);
if (ddef->fns &&
(error = diff_driver_add_patterns(
drv, ddef->fns, ddef->flags | REG_EXTENDED)) < 0)
goto done;
if (ddef->words &&
(error = regcomp(
&drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED)))
{
error = giterr_set_regex(&drv->word_pattern, error);
goto done;
}
git_strmap_insert(reg->drivers, drv->name, drv, error);
if (error > 0)
error = 0;
done:
if (error && drv)
git_diff_driver_free(drv);
else
*out = drv;
return error;
}
static int git_diff_driver_load(
git_diff_driver **out, git_repository *repo, const char *driver_name)
{
int error = 0;
git_diff_driver_registry *reg;
git_diff_driver *drv;
git_diff_driver *drv = NULL;
size_t namelen = strlen(driver_name);
khiter_t pos;
git_config *cfg;
......@@ -141,21 +224,19 @@ static int git_diff_driver_load(
const git_config_entry *ce;
bool found_driver = false;
reg = git_repository_driver_registry(repo);
if (!reg)
if ((reg = git_repository_driver_registry(repo)) == NULL)
return -1;
else {
pos = git_strmap_lookup_index(reg->drivers, driver_name);
if (git_strmap_valid_index(reg->drivers, pos)) {
*out = git_strmap_value_at(reg->drivers, pos);
return 0;
}
pos = git_strmap_lookup_index(reg->drivers, driver_name);
if (git_strmap_valid_index(reg->drivers, pos)) {
*out = git_strmap_value_at(reg->drivers, pos);
return 0;
}
/* if you can't read config for repo, just use default driver */
if (git_repository_config__weakptr(&cfg, repo) < 0) {
giterr_clear();
return GIT_ENOTFOUND;
goto done;
}
drv = git__calloc(1, sizeof(git_diff_driver) + namelen + 1);
......@@ -178,7 +259,7 @@ static int git_diff_driver_load(
found_driver = true;
break;
default:
/* diff.<driver>.binary unspecified, so just continue */
/* diff.<driver>.binary unspecified or "auto", so just continue */
break;
}
......@@ -234,14 +315,18 @@ static int git_diff_driver_load(
git_strmap_insert(reg->drivers, drv->name, drv, error);
if (error < 0)
goto done;
error = 0;
*out = drv;
done:
git_buf_free(&name);
if (!*out)
*out = &global_drivers[DIFF_DRIVER_AUTO];
if (!*out) {
int error2 = git_diff_driver_builtin(out, reg, driver_name);
if (!error)
error = error2;
}
if (drv && drv != *out)
git_diff_driver_free(drv);
......@@ -256,14 +341,13 @@ int git_diff_driver_lookup(
const char *value;
assert(out);
*out = NULL;
if (!repo || !path || !strlen(path))
goto use_auto;
if ((error = git_attr_get(&value, repo, 0, path, "diff")) < 0)
return error;
if (GIT_ATTR_UNSPECIFIED(value))
/* just use the auto value */;
else if ((error = git_attr_get(&value, repo, 0, path, "diff")) < 0)
/* return error below */;
else if (GIT_ATTR_UNSPECIFIED(value))
/* just use the auto value */;
else if (GIT_ATTR_FALSE(value))
*out = &global_drivers[DIFF_DRIVER_BINARY];
......@@ -272,17 +356,16 @@ int git_diff_driver_lookup(
/* otherwise look for driver information in config and build driver */
else if ((error = git_diff_driver_load(out, repo, value)) < 0) {
if (error != GIT_ENOTFOUND)
return error;
else
if (error == GIT_ENOTFOUND) {
error = 0;
giterr_clear();
}
}
use_auto:
if (!*out)
*out = &global_drivers[DIFF_DRIVER_AUTO];
return 0;
return error;
}
void git_diff_driver_free(git_diff_driver *driver)
......@@ -293,7 +376,7 @@ void git_diff_driver_free(git_diff_driver *driver)
return;
for (i = 0; i < git_array_size(driver->fn_patterns); ++i)
regfree(git_array_get(driver->fn_patterns, i));
regfree(& git_array_get(driver->fn_patterns, i)->re);
git_array_clear(driver->fn_patterns);
regfree(&driver->word_pattern);
......@@ -330,23 +413,34 @@ int git_diff_driver_content_is_binary(
}
static int diff_context_line__simple(
git_diff_driver *driver, const char *line, size_t line_len)
git_diff_driver *driver, git_buf *line)
{
char firstch = line->ptr[0];
GIT_UNUSED(driver);
GIT_UNUSED(line_len);
return (git__isalpha(*line) || *line == '_' || *line == '$');
return (git__isalpha(firstch) || firstch == '_' || firstch == '$');
}
static int diff_context_line__pattern_match(
git_diff_driver *driver, const char *line, size_t line_len)
git_diff_driver *driver, git_buf *line)
{
size_t i;
size_t i, maxi = git_array_size(driver->fn_patterns);
regmatch_t pmatch[2];
GIT_UNUSED(line_len);
for (i = 0; i < maxi; ++i) {
git_diff_driver_pattern *pat = git_array_get(driver->fn_patterns, i);
if (!regexec(&pat->re, line->ptr, 2, pmatch, 0)) {
if (pat->flags & REG_NEGATE)
return false;
/* use pmatch data to trim line data */
i = (pmatch[1].rm_so >= 0) ? 1 : 0;
git_buf_consume(line, git_buf_cstr(line) + pmatch[i].rm_so);
git_buf_truncate(line, pmatch[i].rm_eo - pmatch[i].rm_so);
git_buf_rtrim(line);
for (i = 0; i < git_array_size(driver->fn_patterns); ++i) {
if (!regexec(git_array_get(driver->fn_patterns, i), line, 0, NULL, 0))
return true;
}
}
return false;
......@@ -368,8 +462,7 @@ static long diff_context_find(
if (!ctxt->line.size)
return -1;
if (!ctxt->match_line ||
!ctxt->match_line(ctxt->driver, ctxt->line.ptr, ctxt->line.size))
if (!ctxt->match_line || !ctxt->match_line(ctxt->driver, &ctxt->line))
return -1;
if (out_size > (long)ctxt->line.size)
......
......@@ -31,7 +31,7 @@ typedef long (*git_diff_find_context_fn)(
const char *, long, char *, long, void *);
typedef int (*git_diff_find_context_line)(
git_diff_driver *, const char *, size_t);
git_diff_driver *, git_buf *);
typedef struct {
git_diff_driver *driver;
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_userdiff_h__
#define INCLUDE_userdiff_h__
/*
* This file isolates the built in diff driver function name patterns.
* Most of these patterns are taken from Git (with permission from the
* original authors for relicensing to libgit2).
*/
typedef struct {
const char *name;
const char *fns;
const char *words;
int flags;
} git_diff_driver_definition;
#define WORD_DEFAULT "|[^[:space:]]|[\xc0-\xff][\x80-\xbf]+"
/*
* These builtin driver definition macros have same signature as in core
* git userdiff.c so that the data can be extracted verbatim
*/
#define PATTERNS(NAME, FN_PATS, WORD_PAT) \
{ NAME, FN_PATS, WORD_PAT WORD_DEFAULT, 0 }
#define IPATTERN(NAME, FN_PATS, WORD_PAT) \
{ NAME, FN_PATS, WORD_PAT WORD_DEFAULT, REG_ICASE }
/*
* The table of diff driver patterns
*
* Function name patterns are a list of newline separated patterns that
* match a function declaration (i.e. the line you want in the hunk header),
* or a negative pattern prefixed with a '!' to reject a pattern (such as
* rejecting goto labels in C code).
*
* Word boundary patterns are just a simple pattern that will be OR'ed with
* the default value above (i.e. whitespace or non-ASCII characters).
*/
static git_diff_driver_definition builtin_defs[] = {
IPATTERN("ada",
"!^(.*[ \t])?(is new|renames|is separate)([ \t].*)?$\n"
"!^[ \t]*with[ \t].*$\n"
"^[ \t]*((procedure|function)[ \t]+.*)$\n"
"^[ \t]*((package|protected|task)[ \t]+.*)$",
/* -- */
"[a-zA-Z][a-zA-Z0-9_]*"
"|[0-9][-+0-9#_.eE]"
"|=>|\\.\\.|\\*\\*|:=|/=|>=|<=|<<|>>|<>"),
IPATTERN("fortran",
"!^([C*]|[ \t]*!)\n"
"!^[ \t]*MODULE[ \t]+PROCEDURE[ \t]\n"
"^[ \t]*((END[ \t]+)?(PROGRAM|MODULE|BLOCK[ \t]+DATA"
"|([^'\" \t]+[ \t]+)*(SUBROUTINE|FUNCTION))[ \t]+[A-Z].*)$",
/* -- */
"[a-zA-Z][a-zA-Z0-9_]*"
"|\\.([Ee][Qq]|[Nn][Ee]|[Gg][TtEe]|[Ll][TtEe]|[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|[Aa][Nn][Dd]|[Oo][Rr]|[Nn]?[Ee][Qq][Vv]|[Nn][Oo][Tt])\\."
/* numbers and format statements like 2E14.4, or ES12.6, 9X.
* Don't worry about format statements without leading digits since
* they would have been matched above as a variable anyway. */
"|[-+]?[0-9.]+([AaIiDdEeFfLlTtXx][Ss]?[-+]?[0-9.]*)?(_[a-zA-Z0-9][a-zA-Z0-9_]*)?"
"|//|\\*\\*|::|[/<>=]="),
PATTERNS("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$",
"[^<>= \t]+"),
PATTERNS("java",
"!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
"^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]="
"|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"),
PATTERNS("matlab",
"^[[:space:]]*((classdef|function)[[:space:]].*)$|^%%[[:space:]].*$",
"[a-zA-Z_][a-zA-Z0-9_]*|[-+0-9.e]+|[=~<>]=|\\.[*/\\^']|\\|\\||&&"),
PATTERNS("objc",
/* Negate C statements that can look like functions */
"!^[ \t]*(do|for|if|else|return|switch|while)\n"
/* Objective-C methods */
"^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n"
/* C functions */
"^[ \t]*(([A-Za-z_][A-Za-z_0-9]*[ \t]+)+[A-Za-z_][A-Za-z_0-9]*[ \t]*\\([^;]*)$\n"
/* Objective-C class/protocol definitions */
"^(@(implementation|interface|protocol)[ \t].*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
PATTERNS("pascal",
"^(((class[ \t]+)?(procedure|function)|constructor|destructor|interface|"
"implementation|initialization|finalization)[ \t]*.*)$"
"\n"
"^(.*=[ \t]*(class|record).*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+"
"|<>|<=|>=|:=|\\.\\."),
PATTERNS("perl",
"^package .*\n"
"^sub [[:alnum:]_':]+[ \t]*"
"(\\([^)]*\\)[ \t]*)?" /* prototype */
/*
* Attributes. A regex can't count nested parentheses,
* so just slurp up whatever we see, taking care not
* to accept lines like "sub foo; # defined elsewhere".
*
* An attribute could contain a semicolon, but at that
* point it seems reasonable enough to give up.
*/
"(:[^;#]*)?"
"(\\{[ \t]*)?" /* brace can come here or on the next line */
"(#.*)?$\n" /* comment */
"^(BEGIN|END|INIT|CHECK|UNITCHECK|AUTOLOAD|DESTROY)[ \t]*"
"(\\{[ \t]*)?" /* brace can come here or on the next line */
"(#.*)?$\n"
"^=head[0-9] .*", /* POD */
/* -- */
"[[:alpha:]_'][[:alnum:]_']*"
"|0[xb]?[0-9a-fA-F_]*"
/* taking care not to interpret 3..5 as (3.)(.5) */
"|[0-9a-fA-F_]+(\\.[0-9a-fA-F_]+)?([eE][-+]?[0-9_]+)?"
"|=>|-[rwxoRWXOezsfdlpSugkbctTBMAC>]|~~|::"
"|&&=|\\|\\|=|//=|\\*\\*="
"|&&|\\|\\||//|\\+\\+|--|\\*\\*|\\.\\.\\.?"
"|[-+*/%.^&<>=!|]="
"|=~|!~"
"|<<|<>|<=>|>>"),
PATTERNS("python", "^[ \t]*((class|def)[ \t].*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[jJlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|//=?|<<=?|>>=?|\\*\\*=?"),
PATTERNS("ruby", "^[ \t]*((class|module|def)[ \t].*)$",
/* -- */
"(@|@@|\\$)?[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+|\\?(\\\\C-)?(\\\\M-)?."
"|//=?|[-+*/<>%&^|=!]=|<<=?|>>=?|===|\\.{1,3}|::|[!=]~"),
PATTERNS("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
"[={}\"]|[^={}\" \t]+"),
PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
"\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"),
PATTERNS("cpp",
/* Jump targets or access declarations */
"!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:.*$\n"
/* C/++ functions/methods at top level */
"^([A-Za-z_][A-Za-z_0-9]*([ \t*]+[A-Za-z_][A-Za-z_0-9]*([ \t]*::[ \t]*[^[:space:]]+)?){1,}[ \t]*\\([^;]*)$\n"
/* compound type at top level */
"^((struct|class|enum)[^;]*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
PATTERNS("csharp",
/* Keywords */
"!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n"
/* Methods and constructors */
"^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[<>@._[:alnum:]]+[ \t]*\\(.*\\))[ \t]*$\n"
/* Properties */
"^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[@._[:alnum:]]+)[ \t]*$\n"
/* Type definitions */
"^[ \t]*(((static|public|internal|private|protected|new|unsafe|sealed|abstract|partial)[ \t]+)*(class|enum|interface|struct)[ \t]+.*)$\n"
/* Namespace */
"^[ \t]*(namespace[ \t]+.*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
PATTERNS("php",
"^[ \t]*(((public|private|protected|static|final)[ \t]+)*((class|function)[ \t].*))$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
PATTERNS("javascript",
"^[ \t]*(function[ \t][a-zA-Z_][^\{]*)\n"
"^[ \t]*(var[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*=[ \t]*function[ \t\(][^\{]*)\n"
"^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*[ \t]*:[ \t]*function[ \t\(][^\{]*)",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
};
#undef IPATTERN
#undef PATTERNS
#undef WORD_DEFAULT
#endif
......@@ -861,15 +861,15 @@ void test_diff_blob__using_path_and_attributes(void)
cl_git_pass(git_config_set_bool(cfg, "diff.iam_binary.binary", 1));
cl_git_pass(git_config_set_bool(cfg, "diff.iam_text.binary", 0));
cl_git_pass(git_config_set_string(
cfg, "diff.iam_alphactx.xfuncname", "^[A-Za-z]"));
cfg, "diff.iam_alphactx.xfuncname", "^[A-Za-z].*$"));
cl_git_pass(git_config_set_bool(cfg, "diff.iam_textalpha.binary", 0));
cl_git_pass(git_config_set_string(
cfg, "diff.iam_textalpha.xfuncname", "^[A-Za-z]"));
cfg, "diff.iam_textalpha.xfuncname", "^[A-Za-z].*$"));
cl_git_pass(git_config_set_string(
cfg, "diff.iam_numctx.funcname", "^[0-9]"));
cfg, "diff.iam_numctx.funcname", "^[0-9][0-9]*"));
cl_git_pass(git_config_set_bool(cfg, "diff.iam_textnum.binary", 0));
cl_git_pass(git_config_set_string(
cfg, "diff.iam_textnum.funcname", "^[0-9]"));
cfg, "diff.iam_textnum.funcname", "^[0-9][0-9]*"));
git_config_free(cfg);
cl_git_append2file(
......
......@@ -15,6 +15,23 @@ void test_diff_drivers__cleanup(void)
g_repo = NULL;
}
static void overwrite_filemode(const char *expected, git_buf *actual)
{
size_t offset;
char *found;
found = strstr(expected, "100644");
if (!found)
return;
offset = ((const char *)found) - expected;
if (actual->size < offset + 6)
return;
if (memcmp(&actual->ptr[offset], "100644", 6) != 0)
memcpy(&actual->ptr[offset], "100644", 6);
}
void test_diff_drivers__patterns(void)
{
git_config *cfg;
......@@ -22,7 +39,7 @@ void test_diff_drivers__patterns(void)
git_tree *one;
git_diff *diff;
git_patch *patch;
git_buf buf = GIT_BUF_INIT;
git_buf actual = GIT_BUF_INIT;
const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";
const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n";
const char *expected2 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Heaven delivers on earth the Hour that cannot be\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";
......@@ -45,10 +62,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_equal_s(expected0, buf.ptr);
cl_git_pass(git_patch_to_buf(&actual, patch));
cl_assert_equal_s(expected0, actual.ptr);
git_buf_free(&buf);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
......@@ -60,10 +77,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_equal_s(expected1, buf.ptr);
cl_git_pass(git_patch_to_buf(&actual, patch));
cl_assert_equal_s(expected1, actual.ptr);
git_buf_free(&buf);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
......@@ -75,10 +92,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_equal_s(expected0, buf.ptr);
cl_git_pass(git_patch_to_buf(&actual, patch));
cl_assert_equal_s(expected0, actual.ptr);
git_buf_free(&buf);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
......@@ -92,10 +109,10 @@ void test_diff_drivers__patterns(void)
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_equal_s(expected1, buf.ptr);
cl_git_pass(git_patch_to_buf(&actual, patch));
cl_assert_equal_s(expected1, actual.ptr);
git_buf_free(&buf);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
......@@ -106,17 +123,17 @@ void test_diff_drivers__patterns(void)
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0));
cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H"));
cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H.*$"));
git_config_free(cfg);
cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_assert_equal_s(expected2, buf.ptr);
cl_git_pass(git_patch_to_buf(&actual, patch));
cl_assert_equal_s(expected2, actual.ptr);
git_buf_free(&buf);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
......@@ -129,7 +146,7 @@ void test_diff_drivers__long_lines(void)
git_index *idx;
git_diff *diff;
git_patch *patch;
git_buf buf = GIT_BUF_INIT;
git_buf actual = GIT_BUF_INIT;
const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n";
g_repo = cl_git_sandbox_init("empty_standard_repo");
......@@ -145,18 +162,91 @@ void test_diff_drivers__long_lines(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
cl_assert_equal_sz(1, git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&buf, patch));
cl_git_pass(git_patch_to_buf(&actual, patch));
/* if chmod not supported, overwrite mode bits since anything is possible */
if (!cl_is_chmod_supported()) {
if (buf.size > 72 && memcmp(&buf.ptr[66], "100644", 6) != 0)
memcpy(&buf.ptr[66], "100644", 6);
}
overwrite_filemode(expected, &actual);
cl_assert_equal_s(expected, buf.ptr);
cl_assert_equal_s(expected, actual.ptr);
git_buf_free(&buf);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
}
void test_diff_drivers__builtins(void)
{
git_diff *diff;
git_patch *patch;
git_buf file = GIT_BUF_INIT, actual = GIT_BUF_INIT, expected = GIT_BUF_INIT;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_vector files = GIT_VECTOR_INIT;
size_t i;
char *path, *extension;
g_repo = cl_git_sandbox_init("userdiff");
cl_git_pass(git_path_dirload("userdiff/files", 9, 0, 0, &files));
opts.interhunk_lines = 1;
opts.context_lines = 1;
opts.pathspec.count = 1;
git_vector_foreach(&files, i, path) {
if (git__prefixcmp(path, "files/file."))
continue;
extension = path + strlen("files/file.");
opts.pathspec.strings = &path;
/* do diff with no special driver */
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
cl_assert_equal_sz(1, git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&actual, patch));
git_buf_sets(&expected, "userdiff/expected/nodriver/diff.");
git_buf_puts(&expected, extension);
cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
overwrite_filemode(expected.ptr, &actual);
cl_assert_equal_s(expected.ptr, actual.ptr);
git_buf_clear(&actual);
git_patch_free(patch);
git_diff_free(diff);
/* do diff with driver */
{
FILE *fp = fopen("userdiff/.gitattributes", "w");
fprintf(fp, "*.%s diff=%s\n", extension, extension);
fclose(fp);
}
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
cl_assert_equal_sz(1, git_diff_num_deltas(diff));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&actual, patch));
git_buf_sets(&expected, "userdiff/expected/driver/diff.");
git_buf_puts(&expected, extension);
cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
overwrite_filemode(expected.ptr, &actual);
cl_assert_equal_s(expected.ptr, actual.ptr);
git_buf_clear(&actual);
git_patch_free(patch);
git_diff_free(diff);
git__free(path);
}
git_buf_free(&file);
git_buf_free(&actual);
git_buf_free(&expected);
git_vector_free(&files);
}
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
Unnamed repository; edit this file 'description' to name the repository.
60e3f7b244a5305e2c9fa4ef0e897f3b14f3b8dd refs/heads/master
P pack-1652578900ac63564f2a24b9714529821276ceb9.pack
# pack-refs with: peeled fully-peeled
60e3f7b244a5305e2c9fa4ef0e897f3b14f3b8dd refs/heads/master
<html>
<body>
<h1 id="first section">
<ol>
<li>item 1.1</li>
<li>item 1.2 changed</li>
<li>item 1.3 changed</li>
<li>item 1.4</li>
<li>item 1.5</li>
<li>item 1.6</li>
<li>item 1.7</li>
<li>item 1.8</li>
<li>item 1.9</li>
<li>item 1.10 added</li>
</ol>
</h1>
<h1 id="second section">
<ol>
<li>item 2.1</li>
<li>item 2.2</li>
<li>item 2.3</li>
<li>item 2.4</li>
<li>item 2.5</li>
<li>item 2.6</li>
<li>item 2.7 changed</li>
<li>item 2.7.1 added</li>
<li>item 2.8</li>
</ol>
</h1>
<h1 id="third section">
<ol>
<li>item 3.1</li>
<li>item 3.2</li>
<li>item 3.3</li>
<li>item 3.4</li>
<li>item 3.5</li>
<li>item 3.6</li>
</ol>
</h1>
</body>
</html>
/*
Some code extracted from https://github.com/julianlloyd/scrollReveal.js
which happens to be a trending Javascript repo with an MIT license at
the time I was working on Javascript userdiff support in libgit2
I extracted just some of the code, so I suspect this is no longer valid
Javascript code, but it contains enough example patterns to work.
*/
;(function (window) {
'use strict';
var docElem = window.document.documentElement;
function getViewportH () {
var client = docElem['clientHeight'],
inner = window['innerHeight'],
sample = window['otherProperty'];
return (client < inner) ? inner : client;
}
function getOffset (el) {
var offsetTop = 0,
offsetLeft = 0;
do {
if (!isNaN(el.offsetTop)) {
offsetTop += el.offsetTop + 1;
}
if (!isNaN(el.offsetLeft)) {
offsetLeft += el.offsetLeft;
}
} while (el = el.offsetParent)
return {
top: offsetTop,
left: offsetLeft
}
}
function isElementInViewport (el, h) {
var scrolled = window.pageYOffset,
viewed = scrolled + getViewportH(),
elTop = getOffset(el).top,
elBottom = elTop + el.offsetHeight,
h = h || 0;
return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
}
scrollReveal.prototype = {
_init: function () {
var self = this;
this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
this.scrolled = false;
this.elems.forEach(function (el, i) {
self.animate(el);
});
var scrollHandler = function () {
if (!self.scrolled) {
self.scrolled = true;
setTimeout(function () {
self._scrollPage();
}, 61);
}
};
var resizeHandler = function () {
function delayed() {
self._scrollPage();
self.resizeTimeout = null;
}
if (self.resizeTimeout) {
clearTimeout(self.resizeTimeout);
}
self.resizeTimeout = setTimeout(delayed, 200);
};
window.addEventListener('scroll', scrollHandler, false);
window.addEventListener('resize', resizeHandler, false);
},
/*=============================================================================*/
_scrollPage: function () {
var self = this;
this.elems.forEach(function (el, i) {
if (isElementInViewport(el, self.options.viewportFactor)) {
self.animate(el);
}
});
this.scrolled = false;
this.tested = true;
},
}; // end scrollReveal.prototype
document.addEventListener("DOMContentLoaded", function (evt) {
window.scrollReveal = new scrollReveal();
});
})(window);
<?php
namespace Faker;
/**
* Proxy for other generators, to return only unique values. Works with
* Faker\Generator\Base->unique()
*/
class UniqueGenerator
{
protected $generator;
protected $maxRetries;
protected $moreStuff;
protected $uniques = array();
public function __construct(Generator $generator, $maxRetries)
{
$this->generator = $generator;
$this->maxRetries = $maxRetries + 1;
}
/**
* Catch and proxy all generator calls but return only unique values
*/
public function __get($attribute)
{
return $this->__call($attribute, array());
}
/**
* Catch and proxy all generator calls with arguments but return only unique values
*/
public function __call($name, $arguments)
{
$i = 0;
if (!isset($this->uniques[$name])) {
$this->uniques[$name] = array();
}
do {
$res = call_user_func_array(array($this->generator, $name), $arguments);
$i++;
if ($i >= $this->maxRetries) {
throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
}
} while (in_array($res, $this->uniques[$name]));
$this->uniques[$name][]= $res;
return $res;
}
}
<html>
<body>
<h1 id="first section">
<ol>
<li>item 1.1</li>
<li>item 1.2</li>
<li>item 1.3</li>
<li>item 1.4</li>
<li>item 1.5</li>
<li>item 1.6</li>
<li>item 1.7</li>
<li>item 1.8</li>
<li>item 1.9</li>
</ol>
</h1>
<h1 id="second section">
<ol>
<li>item 2.1</li>
<li>item 2.2</li>
<li>item 2.3</li>
<li>item 2.4</li>
<li>item 2.5</li>
<li>item 2.6</li>
<li>item 2.7</li>
<li>item 2.8</li>
</ol>
</h1>
<h1 id="third section">
<ol>
<li>item 3.1</li>
<li>item 3.2</li>
<li>item 3.3</li>
<li>item 3.4</li>
<li>item 3.5</li>
<li>item 3.6</li>
<li>item 3.7</li>
<li>item 3.8</li>
</ol>
</h1>
</body>
</html>
/*
Some code extracted from https://github.com/julianlloyd/scrollReveal.js
which happens to be a trending Javascript repo with an MIT license at
the time I was working on Javascript userdiff support in libgit2
I extracted just some of the code, so I suspect this is no longer valid
Javascript code, but it contains enough example patterns to work.
*/
;(function (window) {
'use strict';
var docElem = window.document.documentElement;
function getViewportH () {
var client = docElem['clientHeight'],
inner = window['innerHeight'];
return (client < inner) ? inner : client;
}
function getOffset (el) {
var offsetTop = 0,
offsetLeft = 0;
do {
if (!isNaN(el.offsetTop)) {
offsetTop += el.offsetTop;
}
if (!isNaN(el.offsetLeft)) {
offsetLeft += el.offsetLeft;
}
} while (el = el.offsetParent)
return {
top: offsetTop,
left: offsetLeft
}
}
function isElementInViewport (el, h) {
var scrolled = window.pageYOffset,
viewed = scrolled + getViewportH(),
elH = el.offsetHeight,
elTop = getOffset(el).top,
elBottom = elTop + elH,
h = h || 0;
return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
}
scrollReveal.prototype = {
_init: function () {
var self = this;
this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
this.scrolled = false;
// Initialize all scrollreveals, triggering all
// reveals on visible elements.
this.elems.forEach(function (el, i) {
self.animate(el);
});
var scrollHandler = function () {
if (!self.scrolled) {
self.scrolled = true;
setTimeout(function () {
self._scrollPage();
}, 60);
}
};
var resizeHandler = function () {
function delayed() {
self._scrollPage();
self.resizeTimeout = null;
}
if (self.resizeTimeout) {
clearTimeout(self.resizeTimeout);
}
self.resizeTimeout = setTimeout(delayed, 200);
};
window.addEventListener('scroll', scrollHandler, false);
window.addEventListener('resize', resizeHandler, false);
},
/*=============================================================================*/
_scrollPage: function () {
var self = this;
this.elems.forEach(function (el, i) {
if (isElementInViewport(el, self.options.viewportFactor)) {
self.animate(el);
}
});
this.scrolled = false;
},
}; // end scrollReveal.prototype
document.addEventListener("DOMContentLoaded", function (evt) {
window.scrollReveal = new scrollReveal();
});
})(window);
<?php
namespace Faker;
/**
* Proxy for other generators, to return only unique values. Works with
* Faker\Generator\Base->unique()
*/
class UniqueGenerator
{
protected $generator;
protected $maxRetries;
protected $uniques = array();
public function __construct(Generator $generator, $maxRetries)
{
$this->generator = $generator;
$this->maxRetries = $maxRetries;
}
/**
* Catch and proxy all generator calls but return only unique values
*/
public function __get($attribute)
{
return $this->__call($attribute, array());
}
/**
* Catch and proxy all generator calls with arguments but return only unique values
*/
public function __call($name, $arguments)
{
if (!isset($this->uniques[$name])) {
$this->uniques[$name] = array();
}
$i = 0;
do {
$res = call_user_func_array(array($this->generator, $name), $arguments);
$i++;
if ($i > $this->maxRetries) {
throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
}
} while (in_array($res, $this->uniques[$name]));
$this->uniques[$name][]= $res;
return $res;
}
}
diff --git a/files/file.html b/files/file.html
index 872d196..2320e2f 100644
--- a/files/file.html
+++ b/files/file.html
@@ -5,4 +5,4 @@ <h1 id="first section">
<li>item 1.1</li>
- <li>item 1.2</li>
- <li>item 1.3</li>
+ <li>item 1.2 changed</li>
+ <li>item 1.3 changed</li>
<li>item 1.4</li>
@@ -13,2 +13,3 @@ <h1 id="first section">
<li>item 1.9</li>
+ <li>item 1.10 added</li>
</ol>
@@ -23,3 +24,4 @@ <h1 id="second section">
<li>item 2.6</li>
- <li>item 2.7</li>
+ <li>item 2.7 changed</li>
+ <li>item 2.7.1 added</li>
<li>item 2.8</li>
@@ -35,4 +37,2 @@ <h1 id="third section">
<li>item 3.6</li>
- <li>item 3.7</li>
- <li>item 3.8</li>
</ol>
diff --git a/files/file.javascript b/files/file.javascript
index b9f1286..7cd3c5a 100644
--- a/files/file.javascript
+++ b/files/file.javascript
@@ -16,3 +16,4 @@ function getViewportH ()
var client = docElem['clientHeight'],
- inner = window['innerHeight'];
+ inner = window['innerHeight'],
+ sample = window['otherProperty'];
@@ -27,3 +28,3 @@ function getOffset (el)
if (!isNaN(el.offsetTop)) {
- offsetTop += el.offsetTop;
+ offsetTop += el.offsetTop + 1;
}
@@ -43,8 +44,7 @@ function isElementInViewport (el, h)
viewed = scrolled + getViewportH(),
- elH = el.offsetHeight,
elTop = getOffset(el).top,
- elBottom = elTop + elH,
+ elBottom = elTop + el.offsetHeight,
h = h || 0;
- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
+ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
}
@@ -60,4 +60,2 @@ _init: function ()
- // Initialize all scrollreveals, triggering all
- // reveals on visible elements.
this.elems.forEach(function (el, i) {
@@ -71,3 +69,3 @@ var scrollHandler = function ()
self._scrollPage();
- }, 60);
+ }, 61);
}
@@ -101,2 +99,3 @@ _scrollPage: function ()
this.scrolled = false;
+ this.tested = true;
},
diff --git a/files/file.php b/files/file.php
index 63250ad..967d646 100644
--- a/files/file.php
+++ b/files/file.php
@@ -12,2 +12,3 @@ class UniqueGenerator
protected $maxRetries;
+ protected $moreStuff;
protected $uniques = array();
@@ -17,3 +18,3 @@ public function __construct(Generator $generator, $maxRetries)
$this->generator = $generator;
- $this->maxRetries = $maxRetries;
+ $this->maxRetries = $maxRetries + 1;
}
@@ -33,10 +34,10 @@ public function __call($name, $arguments)
{
+ $i = 0;
if (!isset($this->uniques[$name])) {
$this->uniques[$name] = array();
}
- $i = 0;
do {
$res = call_user_func_array(array($this->generator, $name), $arguments);
$i++;
- if ($i > $this->maxRetries) {
+ if ($i >= $this->maxRetries) {
throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
diff --git a/files/file.html b/files/file.html
index 872d196..2320e2f 100644
--- a/files/file.html
+++ b/files/file.html
@@ -5,4 +5,4 @@
<li>item 1.1</li>
- <li>item 1.2</li>
- <li>item 1.3</li>
+ <li>item 1.2 changed</li>
+ <li>item 1.3 changed</li>
<li>item 1.4</li>
@@ -13,2 +13,3 @@
<li>item 1.9</li>
+ <li>item 1.10 added</li>
</ol>
@@ -23,3 +24,4 @@
<li>item 2.6</li>
- <li>item 2.7</li>
+ <li>item 2.7 changed</li>
+ <li>item 2.7.1 added</li>
<li>item 2.8</li>
@@ -35,4 +37,2 @@
<li>item 3.6</li>
- <li>item 3.7</li>
- <li>item 3.8</li>
</ol>
diff --git a/files/file.javascript b/files/file.javascript
index b9f1286..7cd3c5a 100644
--- a/files/file.javascript
+++ b/files/file.javascript
@@ -16,3 +16,4 @@
var client = docElem['clientHeight'],
- inner = window['innerHeight'];
+ inner = window['innerHeight'],
+ sample = window['otherProperty'];
@@ -27,3 +28,3 @@
if (!isNaN(el.offsetTop)) {
- offsetTop += el.offsetTop;
+ offsetTop += el.offsetTop + 1;
}
@@ -43,8 +44,7 @@
viewed = scrolled + getViewportH(),
- elH = el.offsetHeight,
elTop = getOffset(el).top,
- elBottom = elTop + elH,
+ elBottom = elTop + el.offsetHeight,
h = h || 0;
- return (elTop + elH * h) <= viewed && (elBottom) >= scrolled;
+ return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
}
@@ -60,4 +60,2 @@
- // Initialize all scrollreveals, triggering all
- // reveals on visible elements.
this.elems.forEach(function (el, i) {
@@ -71,3 +69,3 @@
self._scrollPage();
- }, 60);
+ }, 61);
}
@@ -101,2 +99,3 @@
this.scrolled = false;
+ this.tested = true;
},
diff --git a/files/file.php b/files/file.php
index 63250ad..967d646 100644
--- a/files/file.php
+++ b/files/file.php
@@ -12,2 +12,3 @@ class UniqueGenerator
protected $maxRetries;
+ protected $moreStuff;
protected $uniques = array();
@@ -17,3 +18,3 @@ class UniqueGenerator
$this->generator = $generator;
- $this->maxRetries = $maxRetries;
+ $this->maxRetries = $maxRetries + 1;
}
@@ -33,10 +34,10 @@ class UniqueGenerator
{
+ $i = 0;
if (!isset($this->uniques[$name])) {
$this->uniques[$name] = array();
}
- $i = 0;
do {
$res = call_user_func_array(array($this->generator, $name), $arguments);
$i++;
- if ($i > $this->maxRetries) {
+ if ($i >= $this->maxRetries) {
throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
<html>
<body>
<h1 id="first section">
<ol>
<li>item 1.1</li>
<li>item 1.2 changed</li>
<li>item 1.3 changed</li>
<li>item 1.4</li>
<li>item 1.5</li>
<li>item 1.6</li>
<li>item 1.7</li>
<li>item 1.8</li>
<li>item 1.9</li>
<li>item 1.10 added</li>
</ol>
</h1>
<h1 id="second section">
<ol>
<li>item 2.1</li>
<li>item 2.2</li>
<li>item 2.3</li>
<li>item 2.4</li>
<li>item 2.5</li>
<li>item 2.6</li>
<li>item 2.7 changed</li>
<li>item 2.7.1 added</li>
<li>item 2.8</li>
</ol>
</h1>
<h1 id="third section">
<ol>
<li>item 3.1</li>
<li>item 3.2</li>
<li>item 3.3</li>
<li>item 3.4</li>
<li>item 3.5</li>
<li>item 3.6</li>
</ol>
</h1>
</body>
</html>
/*
Some code extracted from https://github.com/julianlloyd/scrollReveal.js
which happens to be a trending Javascript repo with an MIT license at
the time I was working on Javascript userdiff support in libgit2
I extracted just some of the code, so I suspect this is no longer valid
Javascript code, but it contains enough example patterns to work.
*/
;(function (window) {
'use strict';
var docElem = window.document.documentElement;
function getViewportH () {
var client = docElem['clientHeight'],
inner = window['innerHeight'],
sample = window['otherProperty'];
return (client < inner) ? inner : client;
}
function getOffset (el) {
var offsetTop = 0,
offsetLeft = 0;
do {
if (!isNaN(el.offsetTop)) {
offsetTop += el.offsetTop + 1;
}
if (!isNaN(el.offsetLeft)) {
offsetLeft += el.offsetLeft;
}
} while (el = el.offsetParent)
return {
top: offsetTop,
left: offsetLeft
}
}
function isElementInViewport (el, h) {
var scrolled = window.pageYOffset,
viewed = scrolled + getViewportH(),
elTop = getOffset(el).top,
elBottom = elTop + el.offsetHeight,
h = h || 0;
return (elTop + el.offsetHeight * h) <= viewed && (elBottom) >= scrolled;
}
scrollReveal.prototype = {
_init: function () {
var self = this;
this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]'));
this.scrolled = false;
this.elems.forEach(function (el, i) {
self.animate(el);
});
var scrollHandler = function () {
if (!self.scrolled) {
self.scrolled = true;
setTimeout(function () {
self._scrollPage();
}, 61);
}
};
var resizeHandler = function () {
function delayed() {
self._scrollPage();
self.resizeTimeout = null;
}
if (self.resizeTimeout) {
clearTimeout(self.resizeTimeout);
}
self.resizeTimeout = setTimeout(delayed, 200);
};
window.addEventListener('scroll', scrollHandler, false);
window.addEventListener('resize', resizeHandler, false);
},
/*=============================================================================*/
_scrollPage: function () {
var self = this;
this.elems.forEach(function (el, i) {
if (isElementInViewport(el, self.options.viewportFactor)) {
self.animate(el);
}
});
this.scrolled = false;
this.tested = true;
},
}; // end scrollReveal.prototype
document.addEventListener("DOMContentLoaded", function (evt) {
window.scrollReveal = new scrollReveal();
});
})(window);
<?php
namespace Faker;
/**
* Proxy for other generators, to return only unique values. Works with
* Faker\Generator\Base->unique()
*/
class UniqueGenerator
{
protected $generator;
protected $maxRetries;
protected $moreStuff;
protected $uniques = array();
public function __construct(Generator $generator, $maxRetries)
{
$this->generator = $generator;
$this->maxRetries = $maxRetries + 1;
}
/**
* Catch and proxy all generator calls but return only unique values
*/
public function __get($attribute)
{
return $this->__call($attribute, array());
}
/**
* Catch and proxy all generator calls with arguments but return only unique values
*/
public function __call($name, $arguments)
{
$i = 0;
if (!isset($this->uniques[$name])) {
$this->uniques[$name] = array();
}
do {
$res = call_user_func_array(array($this->generator, $name), $arguments);
$i++;
if ($i >= $this->maxRetries) {
throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a unique value', $this->maxRetries));
}
} while (in_array($res, $this->uniques[$name]));
$this->uniques[$name][]= $res;
return $res;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment