From 3d18446acef5462e946fe79909b198b35c2bbfa0 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sun, 29 May 2016 01:23:34 +0300 Subject: Port to MinGW --- bpkg/archive.cxx | 14 ++++++++- bpkg/auth.cxx | 8 +++-- bpkg/buildfile | 3 +- bpkg/checksum.cxx | 7 ++++- bpkg/fetch.cxx | 42 +++++++++++++++------------ bpkg/pkg-unpack.cxx | 6 ++++ bpkg/rep-create.cxx | 9 ++++-- tests/test.sh | 84 ++++++++++++++++++++++++++++++++++++++--------------- 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 "") + $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 <