László Csomor has uploaded this change for review.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
Uncovered https://github.com/bazelbuild/bazel/issues/3148
Change-Id: Iabe06ad4cccb36bef34d3ab68bb4b294390440d3
RELNOTES: Windows: bazel clean --expunge works
---
M src/BUILD
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
A src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
A src/test/py/bazel/test_base.py
6 files changed, 347 insertions(+), 6 deletions(-)
diff --git a/src/BUILD b/src/BUILD
index 2d95161..16194e1 100644
--- a/src/BUILD
+++ b/src/BUILD
@@ -369,6 +369,7 @@
"//src/test/java/com/google/devtools/build/lib:srcs",
"//src/test/java/com/google/devtools/build/skyframe:srcs",
"//src/test/java/com/google/devtools/common/options:srcs",
+ "//src/test/py/bazel:srcs",
"//src/test/shell:srcs",
"//src/tools/android/java/com/google/devtools/build/android:srcs",
"//src/tools/benchmark:srcs",
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index fb4f3ec..088208b 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -711,8 +711,8 @@
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// We redirect stdin to the NUL device, and redirect stdout and stderr to
- // `output_file` (opened below) by telling CreateProcess to use these file
- // handles, so they must be inheritable.
+ // `stdout_file` and `stderr_file` (opened below) by telling CreateProcess to
+ // use these file handles, so they must be inheritable.
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
@@ -724,19 +724,36 @@
"ExecuteDaemon: Could not open NUL device");
}
- windows_util::AutoHandle output_file(
+ windows_util::AutoHandle stdout_file(
CreateJvmOutputFile(wdaemon_output.c_str(), &sa));
- if (!output_file.IsValid()) {
+ if (!stdout_file.IsValid()) {
pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
"ExecuteDaemon: CreateJvmOutputFile %ls", wdaemon_output.c_str());
}
+ HANDLE stderr_handle;
+ // We must duplicate the handle to stdout, otherwise "bazel clean --expunge"
+ // won't work, because when it tries to close stdout then stderr, the former
+ // will succeed but the latter will appear to be valid yet still fail to
+ // close.
+ if (!DuplicateHandle(
+ /* hSourceProcessHandle */ GetCurrentProcess(),
+ /* hSourceHandle */ stdout_file,
+ /* hTargetProcessHandle */ GetCurrentProcess(),
+ /* lpTargetHandle */ &stderr_handle,
+ /* dwDesiredAccess */ 0,
+ /* bInheritHandle */ TRUE,
+ /* dwOptions */ DUPLICATE_SAME_ACCESS)) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "ExecuteDaemon: DuplicateHandle %ls", wdaemon_output.c_str());
+ }
+ windows_util::AutoHandle stderr_file(stderr_handle);
PROCESS_INFORMATION processInfo = {0};
STARTUPINFOA startupInfo = {0};
startupInfo.hStdInput = devnull;
- startupInfo.hStdError = output_file;
- startupInfo.hStdOutput = output_file;
+ startupInfo.hStdError = stdout_file;
+ startupInfo.hStdOutput = stderr_handle;
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
CmdLine cmdline;
CreateCommandLine(&cmdline, exe, args_vector);
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
index 93952a1..352c196 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
@@ -34,7 +34,10 @@
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsProvider;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.logging.LogManager;
import java.util.logging.Logger;
/** Implements 'blaze clean'. */
@@ -227,6 +230,18 @@
if (expunge) {
LOG.info("Expunging...");
env.getRuntime().prepareForAbruptShutdown();
+ // Close java.log.
+ LogManager.getLogManager().reset();
+ // Close the default stdout/stderr.
+ if (FileDescriptor.out.valid()) {
+ new FileOutputStream(FileDescriptor.out).close();
+ }
+ if (FileDescriptor.err.valid()) {
+ new FileOutputStream(FileDescriptor.err).close();
+ }
+ // Close the redirected stdout/stderr.
+ System.out.close();
+ System.err.close();
// Delete the big subdirectories with the important content first--this
// will take the most time. Then quickly delete the little locks, logs
// and links right before we exit. Once the lock file is gone there will
diff --git a/src/test/py/bazel/BUILD b/src/test/py/bazel/BUILD
new file mode 100644
index 0000000..eea2abd
--- /dev/null
+++ b/src/test/py/bazel/BUILD
@@ -0,0 +1,31 @@
+package(default_visibility = ["//visibility:private"])
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]) + [
+ "//src/test/shell/bazel/android:srcs",
+ "//src/test/shell/bazel/apple:srcs",
+ "//src/test/shell/bazel/testdata:srcs",
+ ],
+ visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+ name = "test-deps",
+ testonly = 1,
+ srcs = ["//src:bazel"],
+)
+
+py_library(
+ name = "test_base",
+ srcs = ["test_base.py"],
+ data = [":test-deps"],
+ testonly = 1,
+)
+
+py_test(
+ name = "bazel_clean_test",
+ size = "medium",
+ srcs = ["bazel_clean_test.py"],
+ deps = [":test_base"],
+)
diff --git a/src/test/py/bazel/bazel_clean_test.py b/src/test/py/bazel/bazel_clean_test.py
new file mode 100644
index 0000000..a5affed
--- /dev/null
+++ b/src/test/py/bazel/bazel_clean_test.py
@@ -0,0 +1,60 @@
+# Copyright 2017 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import datetime
+import os
+import subprocess
+import unittest
+from src.test.py.bazel import test_base
+
+
+class BazelCleanTest(test_base.TestBase):
+
+ def testBazelClean(self):
+ self.ScratchFile('WORKSPACE')
+ self.ScratchFile('foo/BUILD', ['genrule(',
+ ' name = "x",',
+ ' outs = ["x.out"],',
+ ' cmd = "touch $@",',
+ ')'])
+
+ exit_code, stdout, _ = self.RunBazel(['info', 'bazel-genfiles'])
+ self.assertEqual(exit_code, 0)
+ bazel_genfiles = stdout[0]
+
+ exit_code, stdout, _ = self.RunBazel(['info', 'output_base'])
+ self.assertEqual(exit_code, 0)
+ output_base = stdout[0]
+
+ exit_code, _, _ = self.RunBazel(['build', '//foo:x'])
+ self.assertEqual(exit_code, 0)
+ self.assertTrue(os.path.exists(os.path.join(bazel_genfiles, 'foo/x.out')))
+
+ exit_code, _, _ = self.RunBazel(['clean'])
+ self.assertEqual(exit_code, 0)
+ self.assertFalse(os.path.exists(os.path.join(bazel_genfiles, 'foo/x.out')))
+ self.assertTrue(os.path.exists(output_base))
+
+ exit_code, _, _ = self.RunBazel(['build', '//foo:x'])
+ self.assertEqual(exit_code, 0)
+ self.assertTrue(os.path.exists(os.path.join(bazel_genfiles, 'foo/x.out')))
+
+ exit_code, _, _ = self.RunBazel(['clean', '--expunge'])
+ self.assertEqual(exit_code, 0)
+ self.assertFalse(os.path.exists(os.path.join(bazel_genfiles, 'foo/x.out')))
+ self.assertFalse(os.path.exists(output_base))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/src/test/py/bazel/test_base.py b/src/test/py/bazel/test_base.py
new file mode 100644
index 0000000..d9220e8
--- /dev/null
+++ b/src/test/py/bazel/test_base.py
@@ -0,0 +1,217 @@
+# Copyright 2017 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import subprocess
+import unittest
+
+
+class Error(Exception):
+ """Base class for errors in this module."""
+ pass
+
+
+class ArgumentError(Error):
+ """A function received a bad argument."""
+ pass
+
+
+class EnvVarUndefinedError(Error):
+ """An expected environment variable is not defined."""
+
+ def __init__(self, name):
+ Error(self, 'Environment variable "%s" is not defined' % name)
+
+
+class TestBase(unittest.TestCase):
+
+ _stderr = None
+ _stdout = None
+ _runfiles = None
+ _temp = None
+ _tests_root = None
+
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+ if self._runfiles is None:
+ self._runfiles = TestBase._LoadRunfiles()
+ test_tmpdir = TestBase.GetEnv('TEST_TMPDIR')
+ self._stdout = os.path.join(test_tmpdir, 'bazel.stdout')
+ self._stderr = os.path.join(test_tmpdir, 'bazel.stderr')
+ self._temp = os.path.join(test_tmpdir, 'tmp')
+ self._tests_root = os.path.join(test_tmpdir, 'tests_root')
+ os.mkdir(self._tests_root)
+ os.chdir(self._tests_root)
+
+
+ @staticmethod
+ def GetEnv(name, default=None):
+ """Returns environment variable `name`.
+
+ Args:
+ name: string; name of the environment variable
+ default: anything; return this value if the envvar is not defined
+ Returns:
+ string, the envvar's value if defined, or `default` if the envvar is not
+ defined but `default` is
+ Raises:
+ EnvVarUndefinedError: if `name` is not a defined envvar and `default` is
+ None
+ """
+ value = os.getenv(name, '__undefined_envvar__')
+ if value == '__undefined_envvar__':
+ if default:
+ return default
+ raise EnvVarUndefinedError(name)
+ return value
+
+
+ @staticmethod
+ def IsWindows():
+ """Returns true if the current platform is Windows."""
+ return os.name == 'nt'
+
+
+ def Path(self, path):
+ """Returns the absolute path of `path` relative to the scratch directory.
+
+ Args:
+ path: string; a path, relative to the test's scratch directory,
+ e.g. "foo/bar/BUILD"
+ Returns:
+ an absolute path
+ Raises:
+ ArgumentError: if `path` is absolute or contains uplevel references
+ """
+ if os.path.isabs(path) or '..' in path:
+ raise ArgumentError(('path="%s" may not be absolute and may not contain ' +
+ 'uplevel references') % path)
+ return os.path.join(self._tests_root, path)
+
+
+ def Rlocation(self, runfile):
+ """Returns the location of a runfile."""
+ return self._runfiles.get(runfile)
+
+
+ def ScratchDir(self, path):
+ """Creates directories under the test's scratch directory.
+
+ Args:
+ path: string; a path, relative to the test's scratch directory,
+ e.g. "foo/bar"
+ Raises:
+ ArgumentError: if `path` is absolute or contains uplevel references
+ IOError: if an I/O error occurs
+ """
+ if not path:
+ return
+ abspath = self.Path(path)
+ if os.path.exists(abspath) and not os.path.isdir(abspath):
+ raise IOError('"%s" (%s) exists and is not a directory' % (path, abspath))
+ os.makedirs(abspath)
+
+
+ def ScratchFile(self, path, lines=None):
+ """Creates a file under the test's scratch directory.
+
+ Args:
+ path: string; a path, relative to the test's scratch directory,
+ e.g. "foo/bar/BUILD"
+ lines: [string]; the contents of the file (newlines are added
+ automatically)
+ Raises:
+ ArgumentError: if `path` is absolute or contains uplevel references
+ IOError: if an I/O error occurs
+ """
+ if not path:
+ return
+ abspath = self.Path(path)
+ if os.path.exists(abspath) and not os.path.isfile(abspath):
+ raise IOError('"%s" (%s) exists and is not a file' % (path, abspath))
+ self.ScratchDir(os.path.dirname(path))
+ with open(abspath, 'w') as f:
+ if lines:
+ for l in lines:
+ f.write(l)
+ f.write('\n')
+
+
+ def RunBazel(self, args):
+ """Runs "bazel <args>", waits for it to exit.
+
+ Args:
+ args: [string]; flags to pass to bazel (e.g. ['--batch', 'build', '//x'])
+ Returns:
+ (int, [string], [string]) tuple: exit code, stdout lines, stderr lines
+ """
+ with open(self._stdout, 'w') as stdout:
+ with open(self._stderr, 'w') as stderr:
+ proc = subprocess.Popen(
+ [self.Rlocation('io_bazel/src/bazel'),
+ '--bazelrc=/dev/null', '--nomaster_bazelrc'] + args,
+ stdout=stdout, stderr=stderr,
+ cwd=self._tests_root,
+ env=self._BazelEnvMap())
+ exit_code = proc.wait()
+
+ with open(self._stdout, 'r') as f:
+ stdout = [l.strip() for l in f.readlines()]
+ with open(self._stderr, 'r') as f:
+ stderr = [l.strip() for l in f.readlines()]
+ return exit_code, stdout, stderr
+
+
+ def _BazelEnvMap(self):
+ """Returns the environment variable map to run Bazel."""
+ if TestBase.IsWindows():
+ def _Visit(result, dirname, names):
+ result.extend(n for n in names if n.startswith('jdk'))
+ while names:
+ names.pop()
+ result = []
+ os.path.walk('c:\\program files\\java\\', _Visit, result)
+ env = {'SYSTEMROOT': TestBase.GetEnv('SYSTEMROOT'),
+ 'JAVA_HOME': 'c:\\program files\\java\\' + sorted(result)[-1],
+ 'BAZEL_SH': 'c:\\tools\\msys64\\usr\\bin\\bash.exe'}
+ else:
+ env = {'BAZEL_SH': TestBase.GetEnv('BAZEL_SH'),
+ 'JAVA_HOME': TestBase.GetEnv('JAVA_HOME')}
+
+ # TODO(laszlocsomor): Let Bazel pass BAZEL_SH and JAVA_HOME to tests and
+ # use those here instead of hardcoding paths.
+ env['PATH'] = TestBase.GetEnv('PATH')
+ env['TMP'] = self._temp
+ return env
+
+
+ @staticmethod
+ def _LoadRunfiles():
+ """Loads the runfiles manifest from ${TEST_SRCDIR}/MANIFEST.
+
+ Returns:
+ {string: string} dictionary, keys are runfiles-relative paths, values are
+ absolute paths that the runfiles entry is mapped to
+ """
+ result = {}
+ path = os.path.join(TestBase.GetEnv('TEST_SRCDIR'), 'MANIFEST')
+ with open(path, 'r') as f:
+ for l in f.readlines():
+ tokens = l.strip().split(' ')
+ if len(tokens) == 2:
+ result[tokens[0]] = tokens[1]
+ return result
+
+
To view, visit change 11919. To unsubscribe, visit settings.
László Csomor abandoned this change.
To view, visit change 11919. To unsubscribe, visit settings.
László Csomor has uploaded this change for review.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
Uncovered https://github.com/bazelbuild/bazel/issues/3148
Change-Id: I692f2e86a5983cb472a142a093611fd1c694cd3b
RELNOTES: Windows: bazel clean --expunge works
---
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
M src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
M src/test/py/bazel/test_base.py
5 files changed, 105 insertions(+), 8 deletions(-)
index 058dfc5..3db1318 100644
--- a/src/test/py/bazel/BUILD
+++ b/src/test/py/bazel/BUILD
@@ -25,3 +25,10 @@
srcs = ["bazel_server_mode_test.py"],
deps = [":test_base"],
index 81ed5dc..e9e407e 100644
--- a/src/test/py/bazel/test_base.py
+++ b/src/test/py/bazel/test_base.py
@@ -226,5 +226,3 @@
if len(tokens) == 2:
result[tokens[0]] = tokens[1]
return result
-
-
To view, visit change 11930. To unsubscribe, visit settings.
László Csomor uploaded patch set #2 to this change.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
Change-Id: I692f2e86a5983cb472a142a093611fd1c694cd3b
RELNOTES: Windows: bazel clean --expunge works
---
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
M src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
M src/test/py/bazel/test_base.py
5 files changed, 105 insertions(+), 8 deletions(-)
To view, visit change 11930. To unsubscribe, visit settings.
László Csomor uploaded patch set #3 to this change.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
Change-Id: I692f2e86a5983cb472a142a093611fd1c694cd3b
RELNOTES: Windows: bazel clean --expunge works
---
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
M src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
4 files changed, 105 insertions(+), 6 deletions(-)
To view, visit change 11930. To unsubscribe, visit settings.
László Csomor posted comments on this change.
Patch set 3:Presubmit-Ready +1
Works on Win/Linux/Mac
Yun Peng posted comments on this change.
Patch set 3:Code-Review +1
Nice job! All looks good to me, but it's better Phillip also take a look. ;)
László Csomor uploaded patch set #4 to this change.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
Change-Id: I692f2e86a5983cb472a142a093611fd1c694cd3b
RELNOTES: Windows: bazel clean --expunge works
---
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
M src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
4 files changed, 106 insertions(+), 12 deletions(-)
To view, visit change 11930. To unsubscribe, visit settings.
László Csomor posted comments on this change.
Patch set 4:Presubmit-Ready +1
The latest snapshot (4) undoes the changes from https://github.com/bazelbuild/bazel/commit/956810b6ee24289e457a4b8d0a84ff56eb32c264 because now that Bazel closes its stdout/stderr, it can delete jvm.out
Yun Peng merged this change.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
This change also undoes https://github.com/bazelbuild/bazel/commit/956810b6ee24289e457a4b8d0a84ff56eb32c264 -- since
Bazel now closes its stdout/stderr before
cleaning, jvm.out is also closed so we don't need
to open it with deletion sharing.
RELNOTES: Windows: bazel clean --expunge works
Change-Id: I692f2e86a5983cb472a142a093611fd1c694cd3b
PiperOrigin-RevId: 158682987
---
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
M src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
4 files changed, 103 insertions(+), 12 deletions(-)
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index fb4f3ec..c07fc13 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -628,12 +628,7 @@
HANDLE handle = ::CreateFileW(
/* lpFileName */ path.c_str(),
/* dwDesiredAccess */ GENERIC_READ | GENERIC_WRITE,
- // Share for reading and also for deletion, so `bazel clean
- // --expunge/--expunge_async` can delete this file while the JVM holds
- // an open file descriptor to it (via stdout). Although subsequent
- // writes would not recreate the file after it's deleted, this is fine
- // because --expunge/--expunge_async shut down the Bazel server.
- /* dwShareMode */ FILE_SHARE_READ | FILE_SHARE_DELETE,
+ /* dwShareMode */ FILE_SHARE_READ,
/* lpSecurityAttributes */ sa,
/* dwCreationDisposition */ CREATE_ALWAYS,
/* dwFlagsAndAttributes */ FILE_ATTRIBUTE_NORMAL,
@@ -711,8 +706,8 @@
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// We redirect stdin to the NUL device, and redirect stdout and stderr to
- // `output_file` (opened below) by telling CreateProcess to use these file
- // handles, so they must be inheritable.
+ // `stdout_file` and `stderr_file` (opened below) by telling CreateProcess to
+ // use these file handles, so they must be inheritable.
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
@@ -724,19 +719,36 @@index edda44d..428e97d 100644
--- a/src/test/py/bazel/BUILD
+++ b/src/test/py/bazel/BUILD
@@ -25,3 +25,10 @@
srcs = ["bazel_server_mode_test.py"],
deps = [":test_base"],
)
+
+py_test(
+ name = "bazel_clean_test",
+ size = "medium",
+ srcs = ["bazel_clean_test.py"],
+ deps = [":test_base"],
+)
diff --git a/src/test/py/bazel/bazel_clean_test.py b/src/test/py/bazel/bazel_clean_test.py
new file mode 100644
index 0000000..51f085f
--- /dev/null
+++ b/src/test/py/bazel/bazel_clean_test.py
@@ -0,0 +1,57 @@
+# Copyright 2017 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import unittest
+from src.test.py.bazel import test_base
+
+
+class BazelCleanTest(test_base.TestBase):
+
+ def testBazelClean(self):
+ self.ScratchFile('WORKSPACE')
+ self.ScratchFile('foo/BUILD', [
+ 'genrule(', ' name = "x",', ' outs = ["x.out"],',
+ ' cmd = "touch $@",', ')'
+ ])
To view, visit change 11930. To unsubscribe, visit settings.
Yun Peng uploaded patch set #6 to the change originally created by László Csomor.
Windows: bazel clean --expunge works
Fixes https://github.com/bazelbuild/bazel/issues/1586
Fixes https://github.com/bazelbuild/bazel/issues/2326
This change also undoes https://github.com/bazelbuild/bazel/commit/956810b6ee24289e457a4b8d0a84ff56eb32c264 -- since
Bazel now closes its stdout/stderr before
cleaning, jvm.out is also closed so we don't need
to open it with deletion sharing.
RELNOTES: Windows: bazel clean --expunge works
Change-Id: I692f2e86a5983cb472a142a093611fd1c694cd3b
PiperOrigin-RevId: 158682987
---
M src/main/cpp/blaze_util_windows.cc
M src/main/java/com/google/devtools/build/lib/runtime/commands/CleanCommand.java
M src/test/py/bazel/BUILD
A src/test/py/bazel/bazel_clean_test.py
4 files changed, 103 insertions(+), 12 deletions(-)
To view, visit change 11930. To unsubscribe, visit settings.