aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/archive.cxx14
-rw-r--r--bpkg/auth.cxx8
-rw-r--r--bpkg/buildfile3
-rw-r--r--bpkg/checksum.cxx7
-rw-r--r--bpkg/fetch.cxx42
-rw-r--r--bpkg/pkg-unpack.cxx6
-rw-r--r--bpkg/rep-create.cxx9
-rwxr-xr-xtests/test.sh84
8 files changed, 124 insertions, 49 deletions
diff --git a/bpkg/archive.cxx b/bpkg/archive.cxx
index b0c7ab7..0edf09d 100644
--- a/bpkg/archive.cxx
+++ b/bpkg/archive.cxx
@@ -48,9 +48,21 @@ namespace bpkg
//
args.push_back ("-O");
+ // An archive name that has a colon in it specifies a file or device on a
+ // remote machine. That makes it impossible to use absolute Windows paths
+ // unless we add the --force-local option.
+ //
+ args.push_back ("--force-local");
+
args.push_back ("-xf");
args.push_back (a.string ().c_str ());
- args.push_back (f.string ().c_str ());
+
+ // MSYS tar doesn't find archived file if it's path is provided in Windows
+ // notation.
+ //
+ string fs (f.posix_string ());
+ args.push_back (fs.c_str ());
+
args.push_back (nullptr);
if (verb >= 2)
diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx
index 5296bc8..591c6a5 100644
--- a/bpkg/auth.cxx
+++ b/bpkg/auth.cxx
@@ -679,7 +679,9 @@ namespace bpkg
try
{
- ofdstream os (pr.out_fd);
+ // Write the signature to the openssl process input in the binary mode.
+ //
+ ofdstream os (pr.out_fd, fdtranslate::binary);
os.exceptions (ofdstream::badbit);
for (const auto& c: sm.signature)
@@ -763,7 +765,9 @@ namespace bpkg
process pr (start_openssl (
co, "pkeyutl", {"-sign", "-inkey", key_name.c_str ()}, true, true));
- ifdstream is (pr.in_ofd);
+ // Read the signature from the openssl process output in the binary mode.
+ //
+ ifdstream is (pr.in_ofd, fdtranslate::binary);
is.exceptions (ifdstream::badbit);
try
diff --git a/bpkg/buildfile b/bpkg/buildfile
index dec1aa7..8436c7c 100644
--- a/bpkg/buildfile
+++ b/bpkg/buildfile
@@ -4,8 +4,9 @@
import libs = libbpkg%lib{bpkg}
import libs += libbutl%lib{butl}
-import libs += libodb%lib{odb}
import libs += libodb-sqlite%lib{odb-sqlite}
+import libs += libodb%lib{odb}
+import libs += libsqlite3%lib{sqlite3} # @@ For now for static linking.
exe{bpkg}: \
{hxx cxx}{ archive } \
diff --git a/bpkg/checksum.cxx b/bpkg/checksum.cxx
index 95f2d80..3c9c4e5 100644
--- a/bpkg/checksum.cxx
+++ b/bpkg/checksum.cxx
@@ -269,7 +269,12 @@ namespace bpkg
try
{
- return f (sha256_path, o.sha256_option ());
+ process pr (f (sha256_path, o.sha256_option ()));
+
+ // Prevent any data modifications on the way to the hashing program.
+ //
+ fdmode (pr.out_fd, fdtranslate::binary);
+ return pr;
}
catch (const process_error& e)
{
diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx
index 89c93e2..c4e441a 100644
--- a/bpkg/fetch.cxx
+++ b/bpkg/fetch.cxx
@@ -538,23 +538,26 @@ namespace bpkg
try
{
- ifdstream is (pr.in_ofd);
+ // Unfortunately we cannot read from the original source twice as we do
+ // below for files. There doesn't seem to be anything better than reading
+ // the entire file into memory and then streaming it twice, once to
+ // calculate the checksum and the second time to actually parse. We need
+ // to read the original stream in the binary mode for the checksum
+ // calculation, then use the binary data to create the text stream for
+ // the manifest parsing.
+ //
+ ifdstream is (pr.in_ofd, fdtranslate::binary);
is.exceptions (ifdstream::badbit | ifdstream::failbit);
- // Unfortunately we cannot rewind STDOUT as we do below for files. There
- // doesn't seem to be anything better than reading the entire file into
- // memory and then streaming it twice, once to calculate the checksum
- // and the second time to actually parse.
- //
- stringstream ss;
- ss << is.rdbuf ();
+ stringstream bs (ios::in | ios::out | ios::binary);
+ bs << is.rdbuf ();
is.close ();
- string sha256sum (sha256 (o, ss));
+ string sha256sum (sha256 (o, bs));
- ss.clear (); ss.seekg (0); // Rewind.
+ istringstream ts (bs.str ()); // Text mode.
- manifest_parser mp (ss, url);
+ manifest_parser mp (ts, url);
M m (mp, ignore_unknown);
if (pr.wait ())
@@ -644,16 +647,17 @@ namespace bpkg
try
{
- ifstream ifs;
- ifs.exceptions (ofstream::badbit | ofstream::failbit);
- ifs.open (f.string ());
-
+ // We can not use the same file stream for both calculating the checksum
+ // and reading the manifest. The file should be opened in the binary
+ // mode for the first operation and in the text mode for the second one.
+ //
string sha256sum;
if (o != nullptr)
- {
- sha256sum = sha256 (*o, ifs);
- ifs.seekg (0); // Rewind the file stream.
- }
+ sha256sum = sha256 (*o, f); // Read file in the binary mode.
+
+ ifstream ifs;
+ ifs.exceptions (ofstream::badbit | ofstream::failbit);
+ ifs.open (f.string ()); // Open file in the text mode.
manifest_parser mp (ifs, f.string ());
return make_pair (M (mp, ignore_unknown), move (sha256sum));
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx
index 8eedb1c..4424017 100644
--- a/bpkg/pkg-unpack.cxx
+++ b/bpkg/pkg-unpack.cxx
@@ -172,6 +172,12 @@ namespace bpkg
args.push_back ("-C");
args.push_back (c.string ().c_str ());
+ // An archive name that has a colon in it specifies a file or device on a
+ // remote machine. That makes it impossible to use absolute Windows paths
+ // unless we add the --force-local option.
+ //
+ args.push_back ("--force-local");
+
args.push_back ("-xf");
args.push_back (a.string ().c_str ());
args.push_back (nullptr);
diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx
index 2ab52fb..61e3f81 100644
--- a/bpkg/rep-create.cxx
+++ b/bpkg/rep-create.cxx
@@ -219,7 +219,12 @@ namespace bpkg
{
ofstream ofs;
ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (p.string ());
+
+ // While we can do nothing about repositories files edited on Windows
+ // and littered with the carriage return characters, there is no
+ // reason to litter the auto-generated packages and signature files.
+ //
+ ofs.open (p.string (), ofstream::out | ofstream::binary);
manifest_serializer s (ofs, p.string ());
manifests.serialize (s);
@@ -242,7 +247,7 @@ namespace bpkg
ofstream ofs;
ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (p.string ());
+ ofs.open (p.string (), ofstream::out | ofstream::binary);
manifest_serializer s (ofs, p.string ());
m.serialize (s);
diff --git a/tests/test.sh b/tests/test.sh
index 3a56c10..4752698 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -32,6 +32,12 @@
trap 'exit 1' ERR
+tmp_file=`mktemp`
+
+# Remove temporary file on exit. Cover the case when exit due to an error.
+#
+trap 'rm -f $tmp_file' EXIT
+
function error ()
{
echo "$*" 1>&2
@@ -41,6 +47,10 @@ function error ()
bpkg="../bpkg/bpkg"
cfg=/tmp/conf
+if [ "${MSYSTEM:0:5}" = "MINGW" ]; then
+ msys=y
+fi
+
verbose=n
remote=n
options=
@@ -79,19 +89,16 @@ fi
bpkg="$bpkg $options"
-# Repository location, name, and absolute location prefixes. Note that the
-# local path is carefully crafted so that we end up with the same repository
-# names in both cases. This is necessary for the authentication tests to work
-# in both cases.
+# Repository location and name prefixes. Note that the local path is carefully
+# crafted so that we end up with the same repository names in both cases. This
+# is necessary for the authentication tests to work in both cases.
#
if [ "$remote" = "y" ]; then
rep=https://build2.org/bpkg/1
repn=build2.org/
- repa=$rep
else
rep=pkg/1/build2.org
repn=build2.org/
- repa=`pwd`/$rep
fi
#
@@ -115,10 +122,8 @@ function test ()
if [ -t 0 ]; then
$bpkg $cmd $ops $*
else
- # There is no way to get the exit code in process substitution
- # so ruin the output.
- #
- diff -u - <($bpkg $cmd $ops $* || echo "<invalid output>")
+ $bpkg $cmd $ops $* >$tmp_file
+ diff --strip-trailing-cr -u - $tmp_file
fi
if [ $? -ne 0 ]; then
@@ -196,6 +201,21 @@ function edit ()
mv $path.bak $path
}
+# Repository absolute location from a relative path.
+#
+function location ()
+{
+ if [ "$remote" = "y" ]; then
+ echo $rep/$1
+ elif [ "$msys" = "y" ]; then
+ # Convert Windows path like c:/abc/xyz to the c:\abc\xyz canonical form.
+ #
+ echo `pwd -W`/$rep/$1 | sed 's%/%\\%g'
+ else
+ echo `pwd`/$rep/$1
+ fi
+}
+
##
## Low-level commands.
##
@@ -233,13 +253,13 @@ test rep-create pkg/1/build2.org/common/bar/unstable
fail rep-info # repository location expected
test rep-info --trust-yes $rep/common/foo/testing <<EOF
-${repn}common/foo/testing $repa/common/foo/testing
-complement ${repn}common/foo/stable $repa/common/foo/stable
+${repn}common/foo/testing `location common/foo/testing`
+complement ${repn}common/foo/stable `location common/foo/stable`
libfoo 1.1.0
EOF
test rep-info -m -r -n --trust-yes $rep/common/bar/unstable <<EOF
-${repn}common/bar/unstable $repa/common/bar/unstable
+${repn}common/bar/unstable `location common/bar/unstable`
: 1
location: ../../foo/testing
:
@@ -276,6 +296,26 @@ location: libbar-1.1.1.tar.gz
sha256sum: d09700602ff78ae405b6d4850e34660e939d27676e015a23b549884497c8bb45
EOF
+hello_fp=`rep_cert_fp pkg/1/build2.org/common/hello`
+test rep-info -m -p --trust $hello_fp $rep/common/hello <<EOF
+: 1
+sha256sum: 8d324fa7911038778b215d28805c6546e737e0092f79f7bd167cf2e28f4ad96f
+:
+name: libhello
+version: 1.0.0+1
+summary: The "Hello World" example library
+license: MIT
+tags: c++, hello, world, example
+description: \\
+A simple library that implements the "Hello World" example in C++. Its primary
+goal is to show a canonical build2/bpkg project/package.
+\\
+url: http://www.example.org/libhello
+email: hello-users@example.org
+requires: c++11
+location: libhello-1.0.0+1.tar.gz
+sha256sum: ceff9f39dbff496ece817d6806ab3723b065dcdff1734683fe64a60c103f7f9b
+EOF
##
## cfg-create
@@ -321,7 +361,6 @@ fail cfg-fetch # no repositories
# hello repository
#
-hello_fp=`rep_cert_fp pkg/1/build2.org/common/hello`
test cfg-create --wipe
test cfg-add $rep/common/hello
test cfg-fetch --trust $hello_fp
@@ -361,7 +400,6 @@ test cfg-add $rep/fetch/t1
fail pkg-fetch libfoo/1.0.0 # no packages
test cfg-fetch --trust-yes
fail pkg-fetch libfoo/2+1.0.0 # not available
-
test cfg-create --wipe
test cfg-add $rep/fetch/t1
test cfg-fetch --trust-yes
@@ -1539,44 +1577,44 @@ fail cfg-fetch --trust-yes # packages file signature:mismatch
#
test cfg-create --wipe
test rep-info --trust-no --trust $signed_fp -d $cfg $rep/auth/signed <<EOF
-${repn}auth/signed $repa/auth/signed
+${repn}auth/signed `location auth/signed`
libfoo 1.0.0
EOF
test rep-info --trust-no -d $cfg $rep/auth/signed <<EOF
-${repn}auth/signed $repa/auth/signed
+${repn}auth/signed `location auth/signed`
libfoo 1.0.0
EOF
test cfg-create --wipe
test rep-info --trust-yes $rep/auth/signed <<EOF
-${repn}auth/signed $repa/auth/signed
+${repn}auth/signed `location auth/signed`
libfoo 1.0.0
EOF
fail rep-info --trust-no $rep/auth/signed <<EOF
-${repn}auth/signed $repa/auth/signed
+${repn}auth/signed `location auth/signed`
libfoo 1.0.0
EOF
test cfg-create --wipe
test rep-info --trust-yes -d $cfg $rep/auth/unsigned1 <<EOF
-${repn}auth/unsigned1 $repa/auth/unsigned1
+${repn}auth/unsigned1 `location auth/unsigned1`
libfoo 1.0.0
EOF
test rep-info --trust-no -d $cfg $rep/auth/unsigned2 <<EOF
-${repn}auth/unsigned2 $repa/auth/unsigned2
+${repn}auth/unsigned2 `location auth/unsigned2`
libfoo 1.0.0
EOF
test cfg-create --wipe
test rep-info --trust-yes $rep/auth/unsigned1 <<EOF
-${repn}auth/unsigned1 $repa/auth/unsigned1
+${repn}auth/unsigned1 `location auth/unsigned1`
libfoo 1.0.0
EOF
fail rep-info --trust-no $rep/auth/unsigned1 <<EOF
-${repn}auth/unsigned1 $repa/auth/unsigned1
+${repn}auth/unsigned1 `location auth/unsigned1`
libfoo 1.0.0
EOF