def get_dirty_buck_version(dirpath): git_tree_in = check_output( ['git', 'log', '-n1', '--pretty=format:%T', 'HEAD', '--'], cwd=dirpath).strip() with EmptyTempFile(prefix='buck-git-index') as index_file: new_environ = os.environ.copy() new_environ['GIT_INDEX_FILE'] = index_file.name subprocess.check_call(['git', 'read-tree', git_tree_in], cwd=dirpath, env=new_environ) subprocess.check_call(['git', 'add', '-u'], cwd=dirpath, env=new_environ) git_tree_out = check_output(['git', 'write-tree'], cwd=dirpath, env=new_environ).strip() with EmptyTempFile(prefix='buck-version-uid-input', closed=False) as uid_input: subprocess.check_call(['git', 'ls-tree', '--full-tree', git_tree_out], cwd=dirpath, stdout=uid_input) return check_output(['git', 'hash-object', uid_input.name], cwd=dirpath).strip()
def _is_buckd_running(self): with Tracing('BuckRepo._is_buckd_running'): buckd_socket_path = self._buck_project.get_buckd_socket_path() if not os.path.exists(buckd_socket_path): return False buck_client_file = self._get_resource(CLIENT) command = [buck_client_file] command.append('ng-stats') command.append('--nailgun-server') command.append('local:.buckd/sock') try: check_output( command, cwd=self._buck_project.root, stderr=subprocess.STDOUT) except CalledProcessError as e: if e.returncode == NAILGUN_CONNECTION_REFUSED_CODE: return False else: print(e.output, end='', file=sys.stderr) raise return True
def _setup_watchman_watch(self): with Tracing('BuckRepo._setup_watchman_watch'): if not which('watchman'): message = textwrap.dedent("""\ Watchman not found, please install when using buckd. See https://github.com/facebook/watchman for details.""") if sys.platform == "darwin": message += "\n(brew install watchman on OS X)" # Bail if watchman isn't installed as we know java's # FileSystemWatcher will take too long to process events. raise BuckToolException(message) print("Using watchman.", file=sys.stderr) try: # Check watchman version # We only want to use watch-project in watchman >= 3.4, # since early versions don't return the project path relative to # the repo root. if self._watchman_atleast(3, 4): response = check_output( ['watchman', 'watch-project', self._buck_project.root], stderr=subprocess.STDOUT) else: response = check_output( ['watchman', 'watch', self._buck_project.root], stderr=subprocess.STDOUT) jsonresp = json.loads(response) root = jsonresp.get("watch", self._buck_project.root) relative_path = jsonresp.get('relative_path') return root, relative_path except CalledProcessError as e: print(e.output, end='', file=sys.stderr) raise
def get_dirty_buck_version(dirpath): git_tree_in = check_output( ['git', 'log', '-n1', '--pretty=format:%T', 'HEAD', '--'], cwd=dirpath).strip() with EmptyTempFile(prefix='buck-git-index') as index_file: new_environ = os.environ.copy() new_environ['GIT_INDEX_FILE'] = index_file.name subprocess.check_call( ['git', 'read-tree', git_tree_in], cwd=dirpath, env=new_environ) subprocess.check_call( ['git', 'add', '-A'], cwd=dirpath, env=new_environ) git_tree_out = check_output( ['git', 'write-tree'], cwd=dirpath, env=new_environ).strip() with EmptyTempFile(prefix='buck-version-uid-input', closed=False) as uid_input: subprocess.check_call( ['git', 'ls-tree', '--full-tree', git_tree_out], cwd=dirpath, stdout=uid_input) return check_output( ['git', 'hash-object', uid_input.name], cwd=dirpath).strip()
def kill_buckd(self): with Tracing('BuckRepo.kill_buckd'): buckd_port = self._buck_project.get_buckd_port() if buckd_port: if not buckd_port.isdigit(): print("WARNING: Corrupt buckd port: '{0}'.".format(buckd_port)) else: print("Shutting down nailgun server...", file=sys.stderr) buck_client_file = self._get_resource(CLIENT) command = [buck_client_file] command.append('ng-stop') command.append('--nailgun-port') command.append(buckd_port) try: check_output( command, cwd=self._buck_project.root, stderr=subprocess.STDOUT) except CalledProcessError as e: if (e.returncode not in [NAILGUN_CONNECTION_REFUSED_CODE, NAILGUN_CONNECTION_BROKEN_CODE, NAILGUN_UNEXPECTED_CHUNK_TYPE]): print(e.output, end='', file=sys.stderr) raise self._buck_project.clean_up_buckd()
def _is_buckd_running(self): with Tracing('BuckRepo._is_buckd_running'): buckd_port = self._buck_project.get_buckd_port() if buckd_port is None or not buckd_port.isdigit(): return False buck_client_file = self._get_resource(CLIENT) command = [buck_client_file] command.append('ng-stats') command.append('--nailgun-port') command.append(buckd_port) try: check_output( command, cwd=self._buck_project.root, stderr=subprocess.STDOUT) except CalledProcessError as e: if e.returncode == NAILGUN_CONNECTION_REFUSED_CODE: return False else: print(e.output, end='', file=sys.stderr) raise return True
def kill_buckd(self): with Tracing('BuckRepo.kill_buckd'): buckd_port = self._buck_project.get_buckd_port() if buckd_port: if not buckd_port.isdigit(): print("WARNING: Corrupt buckd port: '{0}'.".format( buckd_port)) else: print("Shutting down nailgun server...", file=sys.stderr) buck_client_file = self._get_resource(CLIENT) command = [buck_client_file] command.append('ng-stop') command.append('--nailgun-port') command.append(buckd_port) try: check_output(command, cwd=self._buck_project.root, stderr=subprocess.STDOUT) except CalledProcessError as e: if (e.returncode not in [ NAILGUN_CONNECTION_REFUSED_CODE, NAILGUN_CONNECTION_BROKEN_CODE, NAILGUN_UNEXPECTED_CHUNK_TYPE ]): print(e.output, end='', file=sys.stderr) raise self._buck_project.clean_up_buckd()
def get_dirty_buck_version(dirpath): git_tree_in = check_output(["git", "log", "-n1", "--pretty=format:%T", "HEAD", "--"], cwd=dirpath).strip() with EmptyTempFile(prefix="buck-git-index") as index_file: new_environ = os.environ.copy() new_environ["GIT_INDEX_FILE"] = index_file.name subprocess.check_call(["git", "read-tree", git_tree_in], cwd=dirpath, env=new_environ) subprocess.check_call(["git", "add", "-A"], cwd=dirpath, env=new_environ) git_tree_out = check_output(["git", "write-tree"], cwd=dirpath, env=new_environ).strip() with EmptyTempFile(prefix="buck-version-uid-input", closed=False) as uid_input: subprocess.check_call(["git", "ls-tree", "--full-tree", git_tree_out], cwd=dirpath, stdout=uid_input) return check_output(["git", "hash-object", uid_input.name], cwd=dirpath).strip()
def _has_local_changes(self): if not self.is_git: return False output = check_output( ['git', 'ls-files', '-m'], cwd=self.buck_dir) return bool(output.strip())
def is_java8(): try: output = check_output(['java', '-version'], stderr=subprocess.STDOUT) version_line = output.strip().splitlines()[0] return re.compile('(openjdk|java) version "1\.8\..*').match(version_line) except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def is_git(dirpath): dot_git = os.path.join(dirpath, ".git") if which("git") and sys.platform != "cygwin": if os.path.exists(dot_git) and os.path.isdir(dot_git): return True output = check_output(["git", "rev-parse", "--is-inside-work-tree"], cwd=dirpath) return output.strip() == "true" return False
def is_java8(): try: output = check_output(['java', '-version'], stderr=subprocess.STDOUT) version_line = output.strip().splitlines()[0] return re.compile('(openjdk|java) version "1\.8\..*').match( version_line) except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def _setup_watchman_watch(self): with Tracing('BuckRepo._setup_watchman_watch'): if not which('watchman'): message = textwrap.dedent("""\ Watchman not found, please install when using buckd. See https://github.com/facebook/watchman for details.""") if sys.platform == "darwin": message += "\n(brew install watchman on OS X)" # Bail if watchman isn't installed as we know java's # FileSystemWatcher will take too long to process events. raise BuckToolException(message) print("Using watchman.", file=sys.stderr) try: check_output(['watchman', 'watch', self._buck_project.root], stderr=subprocess.STDOUT) except CalledProcessError as e: print(e.output, end='', file=sys.stderr) raise
def _watchman_atleast(self, major, minor): """Returns true if the installed watchman is greater than or equal to the given version.""" response = check_output(['watchman', 'version']) version = json.loads(response).get("version") parts = version.split('.') actualmajor = int(parts[0]) actualminor = int(parts[1]) return actualmajor > major or (actualmajor == major and actualminor >= minor)
def is_git(dirpath): dot_git = os.path.join(dirpath, '.git') if(which('git') and sys.platform != 'cygwin'): if(os.path.exists(dot_git) and os.path.isdir(dot_git)): return True output = check_output( ['git', 'rev-parse', '--is-inside-work-tree'], cwd=dirpath) return output.strip() == 'true' return False
def _setup_watchman_watch(self): with Tracing('BuckRepo._setup_watchman_watch'): if not which('watchman'): message = textwrap.dedent("""\ Watchman not found, please install when using buckd. See https://github.com/facebook/watchman for details.""") if sys.platform == "darwin": message += "\n(brew install watchman on OS X)" # Bail if watchman isn't installed as we know java's # FileSystemWatcher will take too long to process events. raise BuckToolException(message) print("Using watchman.", file=sys.stderr) try: check_output( ['watchman', 'watch', self._buck_project.root], stderr=subprocess.STDOUT) except CalledProcessError as e: print(e.output, end='', file=sys.stderr) raise
def is_git(dirpath): dot_git = os.path.join(dirpath, '.git') if which('git') and sys.platform != 'cygwin': if os.path.exists(dot_git) and os.path.isdir(dot_git): return True try: output = check_output( ['git', 'rev-parse', '--is-inside-work-tree'], cwd=dirpath) return output.strip() == 'true' except CalledProcessError: pass return False
def is_java8(): global _java8 if _java8 is not None: return _java8 try: output = check_output(['java', '-version'], stderr=subprocess.STDOUT) version_line = output.strip().splitlines()[0] m = re.compile('(openjdk|java) version "1\.8\..*').match(version_line) _java8 = bool(m) return _java8 except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def is_dirty(dirpath): # Ignore any changes under these paths for the purposes of forcing a rebuild # of Buck itself. IGNORE_PATHS = ["test"] IGNORE_PATHS_RE_GROUP = "|".join([re.escape(e) for e in IGNORE_PATHS]) IGNORE_PATHS_RE = re.compile("^.. (?:" + IGNORE_PATHS_RE_GROUP + ")") if not is_git(dirpath): return False output = check_output(["git", "status", "--porcelain"], cwd=dirpath) output = "\n".join([line for line in output.splitlines() if not IGNORE_PATHS_RE.search(line)]) return bool(output.strip())
def _get_java_version(): """ Returns a Java version string (e.g. "7", "8"). Information is provided by java tool and parsing is based on http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html """ java_version = check_output(["java", "-version"], stderr=subprocess.STDOUT) # extract java version from a string like 'java version "1.8.0_144"' match = re.search("java version \"(?P<version>.+)\"", java_version) if not match: return None return match.group("version").split(".")[1]
def is_java8_or_9(): global _java8_or_9 if _java8_or_9 is not None: return _java8_or_9 try: cmd = ["java", "-Xms64m", "-version"] output = check_output(cmd, stderr=subprocess.STDOUT) version_line = output.strip().splitlines()[0] m = re.compile('(openjdk|java) version "(1\.(8|9)\.|9).*').match(version_line) _java8_or_9 = bool(m) return _java8_or_9 except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def is_java8_or_9(): global _java8_or_9 if _java8_or_9 is not None: return _java8_or_9 try: cmd = ['java', '-Xms64m', '-version'] output = check_output(cmd, stderr=subprocess.STDOUT) version_line = output.strip().splitlines()[0] m = re.compile('(openjdk|java) version "(1\.(8|9)\.|9).*').match(version_line) _java8_or_9 = bool(m) return _java8_or_9 except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def kill_buckd(self): with Tracing('BuckRepo.kill_buckd'): buckd_socket_path = self._buck_project.get_buckd_socket_path() if os.path.exists(buckd_socket_path): print("Shutting down nailgun server...", file=sys.stderr) buck_client_file = self._get_resource(CLIENT) command = [buck_client_file] command.append('ng-stop') command.append('--nailgun-server') command.append("local:.buckd/sock") try: check_output( command, cwd=self._buck_project.root, stderr=subprocess.STDOUT) except CalledProcessError as e: if (e.returncode not in [NAILGUN_CONNECTION_REFUSED_CODE, NAILGUN_CONNECTION_BROKEN_CODE, NAILGUN_UNEXPECTED_CHUNK_TYPE]): print(e.output, end='', file=sys.stderr) raise self._buck_project.clean_up_buckd()
def _is_buckd_running(self): with Tracing('BuckRepo._is_buckd_running'): buckd_port = self._buck_project.get_buckd_port() if buckd_port is None or not buckd_port.isdigit(): return False buck_client_file = self._get_resource(CLIENT) command = [buck_client_file] command.append('ng-stats') command.append('--nailgun-port') command.append(buckd_port) try: check_output(command, cwd=self._buck_project.root, stderr=subprocess.STDOUT) except CalledProcessError as e: if e.returncode == NAILGUN_CONNECTION_REFUSED_CODE: return False else: print(e.output, end='', file=sys.stderr) raise return True
def is_git(dirpath): dot_git = os.path.join(dirpath, '.git') if which('git') and sys.platform != 'cygwin': if os.path.exists(dot_git) and os.path.isdir(dot_git): return True try: with open(os.devnull, 'w') as devnull: output = check_output( ['git', 'rev-parse', '--is-inside-work-tree'], cwd=dirpath, stderr=devnull) return output.strip() == 'true' except CalledProcessError: pass return False
def is_dirty(dirpath): # Ignore any changes under these paths for the purposes of forcing a rebuild # of Buck itself. IGNORE_PATHS = ['test'] IGNORE_PATHS_RE_GROUP = '|'.join([re.escape(e) for e in IGNORE_PATHS]) IGNORE_PATHS_RE = re.compile('^.. (?:' + IGNORE_PATHS_RE_GROUP + ')') if not is_git(dirpath): return False output = check_output( ['git', 'status', '--porcelain'], cwd=dirpath) output = '\n'.join([line for line in output.splitlines() if not IGNORE_PATHS_RE.search(line)]) return bool(output.strip())
def is_java8_or_9(): global _java8_or_9 if _java8_or_9 is not None: return _java8_or_9 try: cmd = ['java', '-Xms64m', '-version'] output = check_output(cmd, stderr=subprocess.STDOUT) for version_line in output.strip().splitlines(): m = re.compile('(openjdk|java) version "(1\.(8|9)\.|9).*').match(version_line) if bool(m): return True return False except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def is_java8_or_9(): global _java8_or_9 if _java8_or_9 is not None: return _java8_or_9 try: cmd = ['java', '-Xms64m', '-version'] output = check_output(cmd, stderr=subprocess.STDOUT, shell=sys.platform == "win32") for version_line in output.strip().splitlines(): m = re.compile('(openjdk|java) version "(1\.(8|9)\.|9).*').match(version_line) if bool(m): return True return False except CalledProcessError as e: print(e.output, file=sys.stderr) raise e
def _environ_for_buck(self): env = os.environ.copy() env['CLASSPATH'] = str(self._get_bootstrap_classpath()) env['BUCK_CLASSPATH'] = str(self._get_java_classpath()) env['BUCK_TTY'] = str(int(sys.stdin.isatty())) if os.name == 'posix': # It will fallback on default on Windows platform. try: # Get the number of columns in the terminal. with open(os.devnull, 'w') as devnull: columns = check_output(["tput", "cols"], stderr=devnull).strip() env['COLUMNS'] = columns except CalledProcessError: # If the call to tput fails, we use the default. pass return env
def _environ_for_buck(self): env = os.environ.copy() env['CLASSPATH'] = str(self._get_bootstrap_classpath()) env['BUCK_CLASSPATH'] = str(self._get_java_classpath()) env['BUCK_TTY'] = str(int(sys.stdin.isatty())) if os.name == 'posix': # It will fallback on default on Windows platform. try: # Get the number of columns in the terminal. with open(os.devnull, 'w') as devnull: stty_size_str = check_output(["stty", "size"], stderr=devnull).strip() stty_size = stty_size_str.split(' ') if len(stty_size) >= 2: env['BUCK_TERM_COLUMNS'] = stty_size[1] except CalledProcessError: # If the call to tput fails, we use the default. pass return env
def get_git_revision_timestamp(dirpath): return check_output(["git", "log", "--pretty=format:%ct", "-1", "HEAD", "--"], cwd=dirpath).strip()
def launch_buck(self, build_id): with Tracing('BuckRepo.launch_buck'): if not is_java8_or_9(): WARNING = '\033[93m' ENDC = '\033[0m' print(WARNING + "::: Buck requires Java 8 or higher." + ENDC, file=sys.stderr) if os_platform == 'darwin': print("::: Available Java homes:", file=sys.stderr) check_output(['/usr/libexec/java_home', '-V']) if not os.environ.get("JAVA_HOME"): print(WARNING + "::: No Java home selected" + ENDC, file=sys.stderr) else: print(WARNING + "::: Selected Java home:" + ENDC, file=sys.stderr) print( WARNING + "::: {0}".format(os.environ.get("JAVA_HOME")) + ENDC, file=sys.stderr) print( WARNING + "::: Select a Java home version 1.8 or higher by setting the JAVA_HOME " + "environment variable to point to one" + ENDC, file=sys.stderr) print( WARNING + "::: Continuing anyway in 30 seconds, but Buck might crash." + ENDC, file=sys.stderr) time.sleep(30) if self._command_line.command == "clean" and not self._command_line.is_help(): self.kill_buckd() buck_version_uid = self._get_buck_version_uid() use_buckd = self._use_buckd() if not self._command_line.is_help(): has_watchman = bool(which('watchman')) if use_buckd and has_watchman: buckd_run_count = self._buck_project.get_buckd_run_count() running_version = self._buck_project.get_running_buckd_version() new_buckd_run_count = buckd_run_count + 1 if (buckd_run_count == MAX_BUCKD_RUN_COUNT or running_version != buck_version_uid): self.kill_buckd() new_buckd_run_count = 0 if new_buckd_run_count == 0 or not self._is_buckd_running(): self.launch_buckd(buck_version_uid=buck_version_uid) else: self._buck_project.update_buckd_run_count(new_buckd_run_count) elif use_buckd and not has_watchman: print("Not using buckd because watchman isn't installed.", file=sys.stderr) elif not use_buckd: print("Not using buckd because NO_BUCKD is set.", file=sys.stderr) env = self._environ_for_buck() env['BUCK_BUILD_ID'] = build_id buck_socket_path = self._buck_project.get_buckd_socket_path() if use_buckd and self._is_buckd_running() and \ os.path.exists(buck_socket_path): with Tracing('buck', args={'command': sys.argv[1:]}): exit_code = 2 last_diagnostic_time = 0 while exit_code == 2: with NailgunConnection('local:.buckd/sock', cwd=self._buck_project.root) as c: exit_code = c.send_command( 'com.facebook.buck.cli.Main', sys.argv[1:], env=env, cwd=self._buck_project.root) if exit_code == 2: now = time.time() if now - last_diagnostic_time > DAEMON_BUSY_MESSAGE_SECONDS: print('Daemon is busy, waiting for it to become free...', file=sys.stderr) last_diagnostic_time = now time.sleep(1) return exit_code command = ["buck"] extra_default_options = [ "-Djava.io.tmpdir={0}".format(self._tmp_dir) ] command.extend(self._get_java_args(buck_version_uid, extra_default_options)) command.append("com.facebook.buck.cli.bootstrapper.ClassLoaderBootstrapper") command.append("com.facebook.buck.cli.Main") command.extend(sys.argv[1:]) return subprocess.call(command, cwd=self._buck_project.root, env=env, executable=which("java"))
def is_java8(): output = check_output(['java', '-version'], stderr=subprocess.STDOUT) version_line = output.strip().splitlines()[0] return re.compile('java version "1\.8\..*').match(version_line)
def get_git_revision(dirpath): output = check_output( ['git', 'rev-parse', 'HEAD', '--'], cwd=dirpath) return output.splitlines()[0].strip()
def get_git_revision(dirpath): output = check_output(["git", "rev-parse", "HEAD", "--"], cwd=dirpath) return output.splitlines()[0].strip()
def get_git_revision(dirpath): output = check_output(['git', 'rev-parse', 'HEAD', '--'], cwd=dirpath) return output.splitlines()[0].strip()
def get_git_revision_timestamp(dirpath): return check_output( ['git', 'log', '--pretty=format:%ct', '-1', 'HEAD', '--'], cwd=dirpath).strip()
def is_dirty(dirpath): output = check_output( ['git', 'status', '--porcelain'], cwd=dirpath) return bool(output.strip())
def platform_path(path): if sys.platform != 'cygwin': return path return check_output(['cygpath', '-w', path]).strip()
def launch_buck(self, build_id): with Tracing('BuckRepo.launch_buck'): if not is_java8_or_9(): WARNING = '\033[93m' ENDC = '\033[0m' print(WARNING + "::: Buck requires Java 8 or higher." + ENDC, file=sys.stderr) if os_platform == 'darwin': print("::: Available Java homes:", file=sys.stderr) check_output(['/usr/libexec/java_home', '-V']) if not os.environ.get("JAVA_HOME"): print(WARNING + "::: No Java home selected" + ENDC, file=sys.stderr) else: print(WARNING + "::: Selected Java home:" + ENDC, file=sys.stderr) print(WARNING + "::: {0}".format(os.environ.get("JAVA_HOME")) + ENDC, file=sys.stderr) print( WARNING + "::: Select a Java home version 1.8 or higher by setting the JAVA_HOME " + "environment variable to point to one" + ENDC, file=sys.stderr) print( WARNING + "::: Continuing anyway in 30 seconds, but Buck might crash." + ENDC, file=sys.stderr) time.sleep(30) if self._command_line.command == "clean" and not self._command_line.is_help( ): self.kill_buckd() buck_version_uid = self._get_buck_version_uid() use_buckd = self._use_buckd() if not self._command_line.is_help(): has_watchman = bool(which('watchman')) if use_buckd and has_watchman: buckd_run_count = self._buck_project.get_buckd_run_count() running_version = self._buck_project.get_running_buckd_version( ) new_buckd_run_count = buckd_run_count + 1 if (buckd_run_count == MAX_BUCKD_RUN_COUNT or running_version != buck_version_uid): self.kill_buckd() new_buckd_run_count = 0 if new_buckd_run_count == 0 or not self._is_buckd_running( ): self.launch_buckd(buck_version_uid=buck_version_uid) else: self._buck_project.update_buckd_run_count( new_buckd_run_count) elif use_buckd and not has_watchman: print("Not using buckd because watchman isn't installed.", file=sys.stderr) elif not use_buckd: print("Not using buckd because NO_BUCKD is set.", file=sys.stderr) env = self._environ_for_buck() env['BUCK_BUILD_ID'] = build_id buck_socket_path = self._buck_project.get_buckd_socket_path() if use_buckd and self._is_buckd_running() and \ os.path.exists(buck_socket_path): with Tracing('buck', args={'command': sys.argv[1:]}): exit_code = 2 last_diagnostic_time = 0 while exit_code == 2: with NailgunConnection( 'local:.buckd/sock', cwd=self._buck_project.root) as c: exit_code = c.send_command( 'com.facebook.buck.cli.Main', sys.argv[1:], env=env, cwd=self._buck_project.root) if exit_code == 2: now = time.time() if now - last_diagnostic_time > DAEMON_BUSY_MESSAGE_SECONDS: print( 'Daemon is busy, waiting for it to become free...', file=sys.stderr) last_diagnostic_time = now time.sleep(1) return exit_code command = ["buck"] extra_default_options = [ "-Djava.io.tmpdir={0}".format(self._tmp_dir) ] command.extend( self._get_java_args(buck_version_uid, extra_default_options)) command.append( "com.facebook.buck.cli.bootstrapper.ClassLoaderBootstrapper") command.append("com.facebook.buck.cli.Main") command.extend(sys.argv[1:]) return subprocess.call(command, cwd=self._buck_project.root, env=env, executable=which("java"))
def is_dirty(dirpath): output = check_output(['git', 'status', '--porcelain'], cwd=dirpath) return bool(output.strip())