def run_commit_hook(name, index): """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance :raises HookExecutionError: """ hp = hook_path(name, index.repo.git_dir) if not os.access(hp, os.X_OK): return env = os.environ.copy() env['GIT_INDEX_FILE'] = index.path env['GIT_EDITOR'] = ':' cmd = subprocess.Popen(hp, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=index.repo.working_dir, close_fds=(os.name == 'posix')) stdout, stderr = cmd.communicate() cmd.stdout.close() cmd.stderr.close() if cmd.returncode != 0: stdout = force_text(stdout, defenc) stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stdout, stderr)
def run_commit_hook(name, index): """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance :raises HookExecutionError: """ hp = hook_path(name, index.repo.git_dir) if not os.access(hp, os.X_OK): return env = os.environ.copy() env['GIT_INDEX_FILE'] = safe_decode(index.path) if PY3 else safe_encode(index.path) env['GIT_EDITOR'] = ':' try: cmd = subprocess.Popen(hp, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=index.repo.working_dir, close_fds=is_posix, creationflags=PROC_CREATIONFLAGS,) except Exception as ex: raise HookExecutionError(hp, ex) else: stdout = [] stderr = [] handle_process_output(cmd, stdout.append, stderr.append, finalize_process) stdout = ''.join(stdout) stderr = ''.join(stderr) if cmd.returncode != 0: stdout = force_text(stdout, defenc) stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stdout, stderr)
def run_commit_hook(name, index, *args): """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance :param args: arguments passed to hook file :raises HookExecutionError: """ hp = hook_path(name, index.repo.git_dir) if not os.access(hp, os.X_OK): return env = os.environ.copy() env['GIT_INDEX_FILE'] = safe_decode(index.path) if PY3 else safe_encode(index.path) env['GIT_EDITOR'] = ':' try: cmd = subprocess.Popen([hp] + list(args), env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=index.repo.working_dir, close_fds=is_posix, creationflags=PROC_CREATIONFLAGS,) except Exception as ex: raise HookExecutionError(hp, ex) else: stdout = [] stderr = [] handle_process_output(cmd, stdout.append, stderr.append, finalize_process) stdout = ''.join(stdout) stderr = ''.join(stderr) if cmd.returncode != 0: stdout = force_text(stdout, defenc) stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stderr, stdout)
def _get_fetch_info_from_stderr(self, proc, progress): progress = to_progress_instance(progress) # skip first line as it is some remote info we are not interested in output = IterableList('name') # lines which are no progress are fetch info lines # this also waits for the command to finish # Skip some progress lines that don't provide relevant information fetch_info_lines = [] # Basically we want all fetch info lines which appear to be in regular form, and thus have a # command character. Everything else we ignore, cmds = set(FetchInfo._flag_map.keys()) progress_handler = progress.new_message_handler() handle_process_output(proc, None, progress_handler, finalizer=None, decode_streams=False) stderr_text = progress.error_lines and '\n'.join( progress.error_lines) or '' proc.wait(stderr=stderr_text) if stderr_text: log.warning("Error lines received while fetching: %s", stderr_text) for line in progress.other_lines: line = force_text(line) for cmd in cmds: if len(line) > 1 and line[0] == ' ' and line[1] == cmd: fetch_info_lines.append(line) continue # read head information with open(osp.join(self.repo.common_dir, 'FETCH_HEAD'), 'rb') as fp: fetch_head_info = [l.decode(defenc) for l in fp.readlines()] l_fil = len(fetch_info_lines) l_fhi = len(fetch_head_info) if l_fil != l_fhi: msg = "Fetch head lines do not match lines provided via progress information\n" msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n" msg += "Will ignore extra progress lines or fetch head lines." msg %= (l_fil, l_fhi) log.debug(msg) log.debug("info lines: " + str(fetch_info_lines)) log.debug("head info : " + str(fetch_head_info)) if l_fil < l_fhi: fetch_head_info = fetch_head_info[:l_fil] else: fetch_info_lines = fetch_info_lines[:l_fhi] # end truncate correct list # end sanity check + sanitization output.extend( FetchInfo._from_line(self.repo, err_line, fetch_line) for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info)) return output
def _get_fetch_info_from_stderr(self, proc, progress): progress = to_progress_instance(progress) # skip first line as it is some remote info we are not interested in output = IterableList('name') # lines which are no progress are fetch info lines # this also waits for the command to finish # Skip some progress lines that don't provide relevant information fetch_info_lines = list() # Basically we want all fetch info lines which appear to be in regular form, and thus have a # command character. Everything else we ignore, cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys()) progress_handler = progress.new_message_handler() stderr_text = None for line in proc.stderr: line = force_text(line) for pline in progress_handler(line): # END handle special messages for cmd in cmds: if len(line) > 1 and line[0] == ' ' and line[1] == cmd: fetch_info_lines.append(line) continue # end find command code # end for each comand code we know # end for each line progress didn't handle # end if progress.error_lines(): stderr_text = '\n'.join(progress.error_lines()) finalize_process(proc, stderr=stderr_text) # read head information fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb') fetch_head_info = [l.decode(defenc) for l in fp.readlines()] fp.close() l_fil = len(fetch_info_lines) l_fhi = len(fetch_head_info) if l_fil != l_fhi: msg = "Fetch head lines do not match lines provided via progress information\n" msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n" msg += "Will ignore extra progress lines or fetch head lines." msg %= (l_fil, l_fhi) log.debug(msg) if l_fil < l_fhi: fetch_head_info = fetch_head_info[:l_fil] else: fetch_info_lines = fetch_info_lines[:l_fhi] # end truncate correct list # end sanity check + sanitization output.extend( FetchInfo._from_line(self.repo, err_line, fetch_line) for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info)) return output
def _get_fetch_info_from_stderr(self, proc, progress): progress = to_progress_instance(progress) # skip first line as it is some remote info we are not interested in output = IterableList('name') # lines which are no progress are fetch info lines # this also waits for the command to finish # Skip some progress lines that don't provide relevant information fetch_info_lines = list() # Basically we want all fetch info lines which appear to be in regular form, and thus have a # command character. Everything else we ignore, cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys()) progress_handler = progress.new_message_handler() stderr_text = None for line in proc.stderr: line = force_text(line) for pline in progress_handler(line): # END handle special messages for cmd in cmds: if len(line) > 1 and line[0] == ' ' and line[1] == cmd: fetch_info_lines.append(line) continue # end find command code # end for each comand code we know # end for each line progress didn't handle # end if progress.error_lines(): stderr_text = '\n'.join(progress.error_lines()) finalize_process(proc, stderr=stderr_text) # read head information fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb') fetch_head_info = [l.decode(defenc) for l in fp.readlines()] fp.close() l_fil = len(fetch_info_lines) l_fhi = len(fetch_head_info) if l_fil != l_fhi: msg = "Fetch head lines do not match lines provided via progress information\n" msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n" msg += "Will ignore extra progress lines or fetch head lines." msg %= (l_fil, l_fhi) log.debug(msg) if l_fil < l_fhi: fetch_head_info = fetch_head_info[:l_fil] else: fetch_info_lines = fetch_info_lines[:l_fhi] # end truncate correct list # end sanity check + sanitization output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line) for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info)) return output
def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None: """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance :param args: arguments passed to hook file :raises HookExecutionError: """ hp = hook_path(name, index.repo.git_dir) if not os.access(hp, os.X_OK): return None env = os.environ.copy() env['GIT_INDEX_FILE'] = safe_decode(str(index.path)) env['GIT_EDITOR'] = ':' cmd = [hp] try: if is_win and not _has_file_extension(hp): # Windows only uses extensions to determine how to open files # (doesn't understand shebangs). Try using bash to run the hook. relative_hp = Path(hp).relative_to( index.repo.working_dir).as_posix() cmd = ["bash.exe", relative_hp] cmd = subprocess.Popen( cmd + list(args), env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=index.repo.working_dir, close_fds=is_posix, creationflags=PROC_CREATIONFLAGS, ) except Exception as ex: raise HookExecutionError(hp, ex) from ex else: stdout_list: List[str] = [] stderr_list: List[str] = [] handle_process_output(cmd, stdout_list.append, stderr_list.append, finalize_process) stdout = ''.join(stdout_list) stderr = ''.join(stderr_list) if cmd.returncode != 0: stdout = force_text(stdout, defenc) stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stderr, stdout)
def _get_fetch_info_from_stderr(self, proc, progress): progress = to_progress_instance(progress) # skip first line as it is some remote info we are not interested in output = IterableList('name') # lines which are no progress are fetch info lines # this also waits for the command to finish # Skip some progress lines that don't provide relevant information fetch_info_lines = [] # Basically we want all fetch info lines which appear to be in regular form, and thus have a # command character. Everything else we ignore, cmds = set(FetchInfo._flag_map.keys()) progress_handler = progress.new_message_handler() handle_process_output(proc, None, progress_handler, finalizer=None, decode_streams=False) stderr_text = progress.error_lines and '\n'.join(progress.error_lines) or '' proc.wait(stderr=stderr_text) if stderr_text: log.warning("Error lines received while fetching: %s", stderr_text) for line in progress.other_lines: line = force_text(line) for cmd in cmds: if len(line) > 1 and line[0] == ' ' and line[1] == cmd: fetch_info_lines.append(line) continue # read head information with open(osp.join(self.repo.common_dir, 'FETCH_HEAD'), 'rb') as fp: fetch_head_info = [l.decode(defenc) for l in fp.readlines()] l_fil = len(fetch_info_lines) l_fhi = len(fetch_head_info) if l_fil != l_fhi: msg = "Fetch head lines do not match lines provided via progress information\n" msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n" msg += "Will ignore extra progress lines or fetch head lines." msg %= (l_fil, l_fhi) log.debug(msg) log.debug("info lines: " + str(fetch_info_lines)) log.debug("head info : " + str(fetch_head_info)) if l_fil < l_fhi: fetch_head_info = fetch_head_info[:l_fil] else: fetch_info_lines = fetch_info_lines[:l_fhi] # end truncate correct list # end sanity check + sanitization output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line) for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info)) return output
def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None: """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance :param args: arguments passed to hook file :raises HookExecutionError: """ hp = hook_path(name, index.repo.git_dir) if not os.access(hp, os.X_OK): return None env = os.environ.copy() env['GIT_INDEX_FILE'] = safe_decode(str(index.path)) env['GIT_EDITOR'] = ':' try: cmd = subprocess.Popen( [hp] + list(args), env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=index.repo.working_dir, close_fds=is_posix, creationflags=PROC_CREATIONFLAGS, ) except Exception as ex: raise HookExecutionError(hp, ex) from ex else: stdout_list = [] # type: List[str] stderr_list = [] # type: List[str] handle_process_output(cmd, stdout_list.append, stderr_list.append, finalize_process) stdout = ''.join(stdout_list) stderr = ''.join(stderr_list) if cmd.returncode != 0: stdout = force_text(stdout, defenc) stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stderr, stdout)
def _value_to_string(self, value: Union[str, bytes, int, float, bool]) -> str: if isinstance(value, (int, float, bool)): return str(value) return force_text(value)
def _value_to_string(self, value): if isinstance(value, (int, float, bool)): return str(value) return force_text(value)
def _get_fetch_info_from_stderr(self, proc: 'Git.AutoInterrupt', progress: Union[Callable[..., Any], RemoteProgress, None], kill_after_timeout: Union[None, float] = None, ) -> IterableList['FetchInfo']: progress = to_progress_instance(progress) # skip first line as it is some remote info we are not interested in output: IterableList['FetchInfo'] = IterableList('name') # lines which are no progress are fetch info lines # this also waits for the command to finish # Skip some progress lines that don't provide relevant information fetch_info_lines = [] # Basically we want all fetch info lines which appear to be in regular form, and thus have a # command character. Everything else we ignore, cmds = set(FetchInfo._flag_map.keys()) progress_handler = progress.new_message_handler() handle_process_output(proc, None, progress_handler, finalizer=None, decode_streams=False, kill_after_timeout=kill_after_timeout) stderr_text = progress.error_lines and '\n'.join(progress.error_lines) or '' proc.wait(stderr=stderr_text) if stderr_text: log.warning("Error lines received while fetching: %s", stderr_text) for line in progress.other_lines: line = force_text(line) for cmd in cmds: if len(line) > 1 and line[0] == ' ' and line[1] == cmd: fetch_info_lines.append(line) continue # read head information fetch_head = SymbolicReference(self.repo, "FETCH_HEAD") with open(fetch_head.abspath, 'rb') as fp: fetch_head_info = [line.decode(defenc) for line in fp.readlines()] l_fil = len(fetch_info_lines) l_fhi = len(fetch_head_info) if l_fil != l_fhi: msg = "Fetch head lines do not match lines provided via progress information\n" msg += "length of progress lines %i should be equal to lines in FETCH_HEAD file %i\n" msg += "Will ignore extra progress lines or fetch head lines." msg %= (l_fil, l_fhi) log.debug(msg) log.debug(b"info lines: " + str(fetch_info_lines).encode("UTF-8")) log.debug(b"head info: " + str(fetch_head_info).encode("UTF-8")) if l_fil < l_fhi: fetch_head_info = fetch_head_info[:l_fil] else: fetch_info_lines = fetch_info_lines[:l_fhi] # end truncate correct list # end sanity check + sanitization for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info): try: output.append(FetchInfo._from_line(self.repo, err_line, fetch_line)) except ValueError as exc: log.debug("Caught error while parsing line: %s", exc) log.warning("Git informed while fetching: %s", err_line.strip()) return output