aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/bash/rule.cxx2
-rw-r--r--libbuild2/cc/install-rule.cxx2
-rw-r--r--libbuild2/cc/link-rule.cxx4
-rw-r--r--libbuild2/file.hxx5
-rw-r--r--libbuild2/filesystem.hxx3
-rw-r--r--libbuild2/parser.cxx73
-rw-r--r--tests/name/pattern.testscript56
7 files changed, 109 insertions, 36 deletions
diff --git a/libbuild2/bash/rule.cxx b/libbuild2/bash/rule.cxx
index 6e96b34..be7b2ff 100644
--- a/libbuild2/bash/rule.cxx
+++ b/libbuild2/bash/rule.cxx
@@ -473,7 +473,7 @@ namespace build2
{
if (!*md.for_install)
fail << "incompatible " << t << " build" <<
- info << "target already built not for install";
+ info << "target already updated but not for install";
}
else
md.for_install = true;
diff --git a/libbuild2/cc/install-rule.cxx b/libbuild2/cc/install-rule.cxx
index 46764a6..c4f924a 100644
--- a/libbuild2/cc/install-rule.cxx
+++ b/libbuild2/cc/install-rule.cxx
@@ -281,7 +281,7 @@ namespace build2
//
if (!*md.for_install)
fail << "incompatible " << t << " build" <<
- info << "target already built not for install";
+ info << "target already updated but not for install";
}
else
md.for_install = true;
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index a669f37..d43e7e8 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -2598,8 +2598,8 @@ namespace build2
//
if (*md->for_install != *d.for_install)
fail << "incompatible " << *l << " build" <<
- info << "library is built " << (*md->for_install ? "" : "not ")
- << "for install";
+ info << "target is already updated but "
+ << (*md->for_install ? "" : "not ") << "for install";
}
auto newer = [&d, l] ()
diff --git a/libbuild2/file.hxx b/libbuild2/file.hxx
index 36e4c00..ff8a821 100644
--- a/libbuild2/file.hxx
+++ b/libbuild2/file.hxx
@@ -30,8 +30,9 @@ namespace build2
// export.build -- export stub
// export/ -- exported buildfiles
//
- // The build/, bootstrap/, root/, and config.build entries are in .gitignore
- // as generated by bdep-new.
+ // The build/, /bootstrap/, /root/, and config.build entries are in
+ // .gitignore as generated by bdep-new (note that build/ is ignored
+ // recursively; see below).
//
// The rest of the filesystem entries are shared between the project and the
// modules that it loads. In particular, if a project loads module named
diff --git a/libbuild2/filesystem.hxx b/libbuild2/filesystem.hxx
index 7b45a08..44f5d92 100644
--- a/libbuild2/filesystem.hxx
+++ b/libbuild2/filesystem.hxx
@@ -24,6 +24,9 @@ namespace build2
{
using butl::entry_type;
+ using butl::dir_entry;
+ using butl::dir_iterator;
+
using butl::auto_rmfile;
using butl::auto_rmdir;
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index 53f808c..cb1bccc 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -2385,9 +2385,16 @@ namespace build2
//
size_t b (0), e (0);
for (size_t m (0), n (text.size ());
- next_word (text, n, b, e, m, '\n', '\r'), b != n;
- sloc.line++)
+ next_word (text, n, b, e, m, '\n', '\r'), b != n; )
{
+ // Treat consecutive \r\n (CRLF) as if they were a single
+ // delimiter.
+ //
+ if (b != 0 && text[b - 1] == '\r' &&
+ e != n && text[e] == '\n' &&
+ m != 2)
+ continue;
+
s.assign (text, b, e - b);
if (!trim (s).empty ())
@@ -2401,6 +2408,8 @@ namespace build2
break;
}
}
+
+ sloc.line++;
}
if (b == e)
@@ -6998,7 +7007,13 @@ namespace build2
// The directory/value must not be empty if we have a type.
//
if (d.empty () && v.empty () && !t.empty ())
- fail (loc) << "typed empty name";
+ {
+ // We sneak +/- in type if in pattern_mode::detect (think {+{}}).
+ //
+ fail (loc) << (t == "+" ? "empty name pattern inclusion group" :
+ t == "-" ? "empty name pattern exclusion group" :
+ "typed empty name");
+ }
ns.emplace_back (move (p), move (d), move (t), move (v), pat);
return ns.back ();
@@ -7258,7 +7273,9 @@ namespace build2
(root_ != nullptr &&
root_->root_extra != nullptr &&
m.to_directory () &&
- exists (d.sp / m / root_->root_extra->buildignore_file)))
+ exists (m.relative ()
+ ? d.sp / m / root_->root_extra->buildignore_file
+ : m / root_->root_extra->buildignore_file)))
return !interm;
// Note that we have to make copies of the extension since there will
@@ -7314,9 +7331,11 @@ namespace build2
return true;
});
+ path pat (move (p));
+
try
{
- path_search (path (move (p)),
+ path_search (pat,
process,
*sp,
path_match_flags::follow_symlinks,
@@ -7324,7 +7343,8 @@ namespace build2
}
catch (const system_error& e)
{
- fail (l) << "unable to scan " << *sp << ": " << e;
+ fail (l) << "unable to scan for '"
+ << (pat.relative () ? *sp / pat : pat) << "': " << e;
}
};
@@ -7569,7 +7589,10 @@ namespace build2
// and look for some wildcards since the pattern can be the result of an
// expansion (or, worse, concatenation). Thus pattern_mode::detect: we
// are going to ask parse_names() to detect for us if the first name is
- // a pattern. And if it is, to refrain from adding pair/dir/type.
+ // a pattern. And if it is, to refrain from adding pair/dir/type (note:
+ // for the pattern inclusions and exclusions the name's type member will
+ // be set to "+" and "-", respectively, and will later be cleared by
+ // expand_name_pattern()).
//
optional<const target_type*> pat_tt (
parse_names (
@@ -8313,16 +8336,42 @@ namespace build2
fail (loc) << "invalid path '" << e.path << "'";
}
- count = parse_names_trailer (
- t, tt, ns, pmode, what, separators, pairn, *pp1, dp1, tp1, cross);
+ // Note that for a pattern inclusion group (see above) we make sure
+ // that the resulting patterns are simple names, passing NULL as the
+ // directory path (the names' type members will still be set to "+"
+ // thought; see the parse_names_trailer::parse() lambda
+ // implementation for details).
+ //
+ assert (!pinc || (tp1 != nullptr && *tp1 == "+"));
- // If empty group or empty name, then this is not a pattern inclusion
- // group (see above).
+ count = parse_names_trailer (
+ t, tt,
+ ns,
+ pmode,
+ what,
+ separators, pairn,
+ *pp1, (!pinc ? dp1 : nullptr), tp1,
+ cross);
+
+ // If empty group, then this is not a pattern inclusion group.
//
if (pinc)
{
- if (count != 0 && (count > 1 || !ns.back ().empty ()))
+ if (count != 0)
+ {
+ // Note that we can never end up with the empty name here. For
+ // example, for the below constructs the above
+ // parse_names_trailer() call would fail with appropriate
+ // diagnostics since the empty name's type will be set to "+"
+ // (see above for details):
+ //
+ // foo/{hxx cxx}{+{}}
+ // foo/{+{}}
+ //
+ assert (count > 1 || !ns.back ().empty ());
+
pattern_detected (ttp);
+ }
ppat = pinc = false;
}
diff --git a/tests/name/pattern.testscript b/tests/name/pattern.testscript
index c1a4ce4..acad250 100644
--- a/tests/name/pattern.testscript
+++ b/tests/name/pattern.testscript
@@ -105,59 +105,70 @@ EOI
:
{
touch foo.txt;
- $* <'print *.txt' >'foo.txt' : simple-file
+ $* <'print *.txt' >'foo.txt' : simple-file
mkdir foo;
- $* <'print */' >/'foo/' : simple-dir
+ $* <'print */' >/'foo/' : simple-dir
touch foo.txt;
- $* <'print {*.txt}' >'foo.txt' : group
+ $* <'print {*.txt}' >'foo.txt' : group
touch foo.txt;
- $* <'print {+*.txt}' >'foo.txt' : plus-prefixed
+ $* <'print {+*.txt}' >'foo.txt' : plus-prefixed
mkdir dir && touch dir/foo.txt;
- $* <'print dir/{*.txt}' >'dir/foo.txt' : dir
+ $* <'print dir/{*.txt}' >'dir/foo.txt' : dir
touch foo.txt;
- $* <'print file{*.txt}' >'file{foo.txt}' : type
+ $* <'print file{*.txt}' >'file{foo.txt}' : type
touch foo.txt;
- $* <'print x@{*.txt}' >'x@foo.txt' : pair
+ $* <'print x@{*.txt}' >'x@foo.txt' : pair
touch bar.txt;
- $* <'print x@dir/file{f*.txt}' >'' : empty
+ $* <'print x@dir/file{f*.txt}' >'' : empty
mkdir dir && touch dir/foo.txt;
- $* <'print **.txt' >/'dir/foo.txt' : recursive
+ $* <'print **.txt' >/'dir/foo.txt' : recursive
mkdir dir && touch dir/foo.txt;
- $* <'print d*/*.txt' >/'dir/foo.txt' : multi-pattern
+ $* <'print d*/*.txt' >/'dir/foo.txt' : multi-pattern
touch foo.txt bar.txt;
- $* <'print {*.txt -bar.txt}' >'foo.txt' : exclude-non-pattern
+ $* <'print {*.txt -bar.txt}' >'foo.txt' : exclude-non-pattern
mkdir baz;
touch foo.txt bar.txt baz/fox.txt baz/box.txt;
- $* <'print {**.txt -b*.txt -b*/*}' >'foo.txt' : exclude-pattern
+ $* <'print {**.txt -b*.txt -b*/*}' >'foo.txt' : exclude-pattern
touch foo.txt bar.txt baz.txt;
- $* <'print {*.txt -{*z.txt bar.txt}}' >'foo.txt' : exclude-group
+ $* <'print {*.txt -{*z.txt bar.txt}}' >'foo.txt' : exclude-group
touch bar.txt;
- $* <'print {f*.txt +bar.txt}' >'bar.txt' : include-non-wildcard
+ $* <'print {f*.txt +bar.txt}' >'bar.txt' : include-non-wildcard
touch bar.txt;
- $* <'print {f*.txt +b*.txt}' >'bar.txt' : include-pattern
+ $* <'print {f*.txt +b*.txt}' >'bar.txt' : include-pattern
mkdir bar;
- $* <'print {f*/ +{b*/}}' >/'bar/' : include-group
+ $* <'print {f*/ +{b*/}}' >/'bar/' : include-group
+
+ mkdir -p foo/bar;
+ $* <'print $path.canonicalize(foo/{+{b*/}})' >/'foo/bar/' : include-group-first
touch foo.txt fox.txt;
- $* <'print {*.txt -f*.txt +*x.txt}' >'fox.txt' : include-exclude-order
+ $* <'print {*.txt -f*.txt +*x.txt}' >'fox.txt' : include-exclude-order
touch foo.txt;
- $* <'print {+foo.txt} {+bar.txt}' >'foo.txt' : non-wildcard
+ $* <'print {+foo.txt} {+bar.txt}' >'foo.txt' : non-wildcard
+
+ mkdir -p foo/bar;
+ touch foo/bar/baz.txt;
+ $* <'print {$src_base/foo/**}' >/"$~/foo/bar/baz.txt" : abs-path-pattern
+
+ mkdir -p foo/bar;
+ touch foo/bar/baz.txt;
+ $* <'print $src_base/foo/{**}' >/"$~/foo/bar/baz.txt" : abs-start-dir
}
: escaping
@@ -309,6 +320,15 @@ EOI
print {+{$pats}}
EOI
+ : pattern-via-expansion-list-subdir
+ :
+ mkdir baz;
+ touch baz/foo.txt baz/bar.hxx;
+ $* <<EOI >'baz/bar.hxx baz/foo.txt'
+ pats = '*.hxx' '*.txt'
+ print baz/{+{$pats}}
+ EOI
+
: pattern-via-expansion-type
:
touch foo.txt;