def backup_user_repos(git, local, max_size, topic, udir, redo, uname, uemail): logger = logging.getLogger('user-repos') for repo in git.get_own_user_repos(): repo_dir = local.get_path(repo['name']) if udir: repo_dir = local.get_path(repo, repo['owner']['login']) if os.path.exists(repo_dir) and redo: # Remove the repo dir so it can be re-created. shutil.rmtree(repo_dir) res = backup_repo(local, repo, logger, max_size, topic, repo['owner']['login'] if udir else None) # Change author/committer ID information if specified. if res and uname and uemail: cmd = [ 'git', 'filter-branch', '-f', '--env-filter', "GIT_AUTHOR_NAME='{}'; GIT_AUTHOR_EMAIL='{}'; GIT_COMMITTER_NAME='{}'; GIT_COMMITTER_EMAIL='{}';" .format(uname, uemail, uname, uemail), '--', '--all' ] proc = subprocess.Popen(cmd, cwd=repo_dir, stdout=subprocess.PIPE) git_std = proc.communicate() for line in git_std: if line: logger.info('{}: {}'.format(repo['name'], line.strip())) # Prune all remotes to sterilize. r = Repo(repo_dir) for remote in r.remotes: Remote.remove(r, remote.name)
def push_remote(*, repo: git.Repo, remote: git.Remote): """ Push the active branch of `repo` to `remote`. """ try: remote.push(all=True) except Exception as e: log(f'Error Pushing to {repo}') raise e
def initRepo(ruta): #En pruebas, NO USAR newRepo = Repo.init(ruta, True) remoto = Remote(newRepo,"MiRepo") remoto.add(newRepo,"MiRepo","https://github.com/annkym/MiRepo.git") remoto.push() print newRepo.git.status()
def load_repository_packages( remote: git.Remote, prefix: str, host: str = "github.com") -> Dict[str, List[Tuple[str, str]]]: print("Loading repository packages...") remote.fetch() url = pathlib.Path(remote.url) raw_url = pathlib.Path(host) / url.parent.name / url.stem / "raw" branches: List[str] = ["any", "stubs"] for platform in ("Linux", "Darwin", "Windows"): for version in ("3.6", "3.7", "3.8"): branches.append(platform + "_" + version) if prefix: for idx in range(len(branches)): branches[idx] += "_" + prefix packages: Dict[str, List[Tuple[str, str]]] = {} for branch in branches: if branch in remote.refs: for t in remote.refs[branch].commit.tree.trees: for b in t.blobs: packages.setdefault(t.name, []) packages[t.name].append(( f"https://{raw_url}/{branch}/{t.name}/{b.name}", b.name, )) return packages
def test_creation_and_removal(self, bare_rw_repo): new_name = "test_new_one" arg_list = (new_name, "git@server:hello.git") remote = Remote.create(bare_rw_repo, *arg_list) assert remote.name == "test_new_one" assert remote in bare_rw_repo.remotes assert remote.exists() # create same one again self.failUnlessRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list) Remote.remove(bare_rw_repo, new_name) assert remote.exists( ) # We still have a cache that doesn't know we were deleted by name remote._clear_cache() assert not remote.exists( ) # Cache should be renewed now. This is an issue ... for remote in bare_rw_repo.remotes: if remote.name == new_name: raise AssertionError("Remote removal failed") # END if deleted remote matches existing remote's name # END for each remote # Issue #262 - the next call would fail if bug wasn't fixed bare_rw_repo.create_remote('bogus', '/bogus/path', mirror='push')
def checkout_branch(repo, branch_name, no_pull=False): """Checkout a branch and optionally pull updates. :param repo: Repo object :param branch_name: Name of the branch to checkout :param no_pull: (Default: False) If True, don't pull changes to branch :return: Head object for the checked out branch """ base_head = Head(repo, f'refs/heads/{branch_name}') if repo.active_branch != base_head: print(f'Checking out {branch_name}.') base_head.checkout() if not no_pull and base_head.tracking_branch(): print(f'Pulling updates to {branch_name}...') remote_name = base_head.tracking_branch().remote_name remote = Remote(repo, remote_name) base_commit = base_head.commit for fetch_info in remote.pull(): if fetch_info.ref == base_head.tracking_branch(): if fetch_info.commit != base_commit: print( f'Updated {branch_name} to {fetch_info.commit.hexsha}') else: print(f'{branch_name} already up to date.') print('') return base_head
def setup_repo(tmp_path: Path) -> Repo: """Set up a repository with the Gafaelfawr Helm chart.""" repo = Repo.init(str(tmp_path)) Remote.create(repo, "origin", "https://github.com/foo/bar") helm_path = Path(__file__).parent / "data" / "kubernetes" chart_path = helm_path / "gafaelfawr" / "Chart.yaml" update_path = tmp_path / "Chart.yaml" shutil.copy(str(chart_path), str(update_path)) repo.index.add(str(update_path)) actor = Actor("Someone", "*****@*****.**") repo.index.commit("Initial commit", author=actor, committer=actor) return repo
def checkout(remoteBranch, localBranch, tag): repo = Repo('.') print('Fetching ' + remoteBranch) if tag: Remote(repo, 'upstream').fetch('refs/tags/' + remoteBranch) else: Remote(repo, 'upstream').fetch(remoteBranch) print('Creating and checking out ' + localBranch) repo.create_head(localBranch, 'FETCH_HEAD').checkout()
def pull(remote: git.Remote): """ Performs a Git pull from a given remote repository. :param remote: git.Remote object. :return: """ log.info("Pulling data from remote '{}'...".format(remote)) try: remote.pull() except git.exc.GitCommandError as git_exc: log.exception("Failed to pull from remote '{}'!".format(remote), exc_info=git_exc) sys.stderr.write("Failed to pull from remote '{}', " "check that git host is online, then restart or perform a manual pull!".format(remote))
def remote_repo_creator(self): rw_daemon_repo_dir = tempfile.mktemp(prefix="daemon_repo-%s-" % func.__name__) rw_repo_dir = tempfile.mktemp(prefix="daemon_cloned_repo-%s-" % func.__name__) rw_daemon_repo = self.rorepo.clone(rw_daemon_repo_dir, shared=True, bare=True) # recursive alternates info ? rw_repo = rw_daemon_repo.clone(rw_repo_dir, shared=True, bare=False, n=True) try: rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_daemon_repo.daemon_export = True # this thing is just annoying ! with rw_daemon_repo.config_writer() as crw: section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # Initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. d_remote = Remote.create(rw_repo, "daemon_origin", rw_daemon_repo_dir) d_remote.fetch() base_daemon_path, rel_repo_dir = osp.split(rw_daemon_repo_dir) remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir)) with d_remote.config_writer as cw: cw.set('url', remote_repo_url) with git_daemon_launched(Git.polish_url(base_daemon_path, is_cygwin=False), # No daemon in Cygwin. '127.0.0.1', GIT_DAEMON_PORT): # Try listing remotes, to diagnose whether the daemon is up. rw_repo.git.ls_remote(d_remote) with cwd(rw_repo.working_dir): try: return func(self, rw_repo, rw_daemon_repo) except: log.info("Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s", rw_repo_dir, rw_daemon_repo_dir) rw_repo_dir = rw_daemon_repo_dir = None raise finally: rw_repo.git.clear_cache() rw_daemon_repo.git.clear_cache() del rw_repo del rw_daemon_repo import gc gc.collect() if rw_repo_dir: rmtree(rw_repo_dir) if rw_daemon_repo_dir: rmtree(rw_daemon_repo_dir)
def get_last_commits(remote: git.Remote, branches: List[str]) -> Dict[str, str]: """Get last commit of each given branch for the given remote.""" last_commits = {} for branch in branches: fetch_info = remote.fetch(branch)[0] last_commits[branch] = fetch_info.commit.hexsha return last_commits
def remote_repo_creator(self): remote_repo_dir = tempfile.mktemp("remote_repo_%s" % func.__name__) repo_dir = tempfile.mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) rw_repo = rw_remote_repo.clone( repo_dir, shared=True, bare=False, n=True) # recursive alternates info ? rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! crw = rw_remote_repo.config_writer() section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # release lock del (crw) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost%s" % remote_repo_dir # some oddity: on windows, python 2.5, it for some reason does not realize # that it has the config_writer property, but instead calls __getattr__ # which will not yield the expected results. 'pinging' the members # with a dir call creates the config_writer property that we require # ... bugs like these make me wonder wheter python really wants to be used # for production. It doesn't happen on linux though. dir(d_remote) d_remote.config_writer.set('url', remote_repo_url) # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError, e: print str(e) if os.name == 'nt': raise AssertionError( 'git-daemon needs to run this test, but windows does not have one. Otherwise, run: git-daemon "%s"' % tempfile.gettempdir()) else: raise AssertionError( 'Please start a git-daemon to run this test, execute: git-daemon "%s"' % tempfile.gettempdir())
def test_creation_and_removal(self, bare_rw_repo): new_name = "test_new_one" arg_list = (new_name, "git@server:hello.git") remote = Remote.create(bare_rw_repo, *arg_list) assert remote.name == "test_new_one" assert remote in bare_rw_repo.remotes assert remote.exists() # create same one again self.failUnlessRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list) Remote.remove(bare_rw_repo, new_name) assert remote.exists() # We still have a cache that doesn't know we were deleted by name remote._clear_cache() assert not remote.exists() # Cache should be renewed now. This is an issue ... for remote in bare_rw_repo.remotes: if remote.name == new_name: raise AssertionError("Remote removal failed")
def _push_branch(self) -> None: """Push the u/neophile branch to GitHub. Raises ------ neophile.exceptions.PushError Pushing the branch to GitHub failed. """ branch = self._repo.head.ref.name remote_url = self._get_authenticated_remote() remote = Remote.add(self._repo, "tmp-neophile", remote_url) try: push_info = remote.push(f"{branch}:{branch}", force=True) for result in push_info: if result.flags & PushInfo.ERROR: msg = f"Pushing {branch} failed: {result.summary}" raise PushError(msg) finally: Remote.remove(self._repo, "tmp-neophile")
async def test_get_github_repo(tmp_path: Path, session: ClientSession) -> None: repo = Repo.init(str(tmp_path)) config = Configuration(github_user="******", github_token="some-token") pr = PullRequester(tmp_path, config, session) remote = Remote.create(repo, "origin", "[email protected]:foo/bar.git") assert pr._get_github_repo() == GitHubRepository(owner="foo", repo="bar") remote.set_url("https://github.com/foo/bar.git") assert pr._get_github_repo() == GitHubRepository(owner="foo", repo="bar") remote.set_url("ssh://[email protected]/foo/bar") assert pr._get_github_repo() == GitHubRepository(owner="foo", repo="bar")
def remote_repo_creator(self): remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__) repo_dir = _mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) rw_repo = rw_remote_repo.clone( repo_dir, shared=True, bare=False, n=True) # recursive alternates info ? rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! crw = rw_remote_repo.config_writer() section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # release lock del (crw) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost%s" % remote_repo_dir d_remote.config_writer.set('url', remote_repo_url) # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError, e: print str(e) if os.name == 'nt': raise AssertionError( 'git-daemon needs to run this test, but windows does not have one. Otherwise, run: git-daemon "%s"' % os.path.dirname(_mktemp())) else: raise AssertionError( 'Please start a git-daemon to run this test, execute: git-daemon "%s"' % os.path.dirname(_mktemp()))
def test_creation_and_removal(self, bare_rw_repo): new_name = "test_new_one" arg_list = (new_name, "git@server:hello.git") remote = Remote.create(bare_rw_repo, *arg_list) assert remote.name == "test_new_one" assert remote in bare_rw_repo.remotes assert remote.exists() # create same one again self.failUnlessRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list) Remote.remove(bare_rw_repo, new_name) assert remote.exists() # We still have a cache that doesn't know we were deleted by name remote._clear_cache() assert not remote.exists() # Cache should be renewed now. This is an issue ... for remote in bare_rw_repo.remotes: if remote.name == new_name: raise AssertionError("Remote removal failed") # END if deleted remote matches existing remote's name # END for each remote # Issue #262 - the next call would fail if bug wasn't fixed bare_rw_repo.create_remote('bogus', '/bogus/path', mirror='push')
def remote_repo_creator(self): remote_repo_dir = tempfile.mktemp("remote_repo_%s" % func.__name__) repo_dir = tempfile.mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) # recursive alternates info ? rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! crw = rw_remote_repo.config_writer() section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # release lock del(crw) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost%s" % remote_repo_dir # some oddity: on windows, python 2.5, it for some reason does not realize # that it has the config_writer property, but instead calls __getattr__ # which will not yield the expected results. 'pinging' the members # with a dir call creates the config_writer property that we require # ... bugs like these make me wonder wheter python really wants to be used # for production. It doesn't happen on linux though. dir(d_remote) d_remote.config_writer.set('url', remote_repo_url) # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError,e: print str(e) if os.name == 'nt': raise AssertionError('git-daemon needs to run this test, but windows does not have one. Otherwise, run: git-daemon "%s"'%tempfile.gettempdir()) else: raise AssertionError('Please start a git-daemon to run this test, execute: git-daemon "%s"'%tempfile.gettempdir())
def remote_repo_creator(self): remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__) repo_dir = _mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) # recursive alternates info ? rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! crw = rw_remote_repo.config_writer() section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # release lock del (crw) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost%s" % remote_repo_dir d_remote.config_writer.set("url", remote_repo_url) # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError, e: print str(e) if os.name == "nt": raise AssertionError( 'git-daemon needs to run this test, but windows does not have one. Otherwise, run: git-daemon "%s"' % os.path.dirname(_mktemp()) ) else: raise AssertionError( 'Please start a git-daemon to run this test, execute: git-daemon "%s"' % os.path.dirname(_mktemp()) )
async def test_get_authenticated_remote(tmp_path: Path, session: ClientSession) -> None: repo = Repo.init(str(tmp_path)) config = Configuration(github_user="******", github_token="some-token") pr = PullRequester(tmp_path, config, session) remote = Remote.create(repo, "origin", "https://github.com/foo/bar") url = pr._get_authenticated_remote() assert url == "https://*****:*****@github.com/foo/bar" remote.set_url("https://[email protected]:8080/foo/bar") url = pr._get_authenticated_remote() assert url == "https://*****:*****@github.com:8080/foo/bar" remote.set_url("[email protected]:bar/foo") url = pr._get_authenticated_remote() assert url == "https://*****:*****@github.com/bar/foo" remote.set_url("ssh://*****:*****@github.com/baz/stuff") url = pr._get_authenticated_remote() assert url == "https://*****:*****@github.com/baz/stuff"
def main(): """Entrypoint to 'gitsync' command-line tool """ parser = argparse.ArgumentParser( description='File-sync integrated with Git system solution tool') parser.add_argument('-d', '--debug', action='store_true', default=False, help='show more message for debugging') parser.add_argument( '--config_file', help= 'Specify the location of the settings (Default value: settings.json)', type=str, default=os.path.join(os.getcwd(), 'settings.json')) parser.add_argument('--init', help='Create a template configuration file', action='store_true', default=False) parser.add_argument('--version', help='Print the GitSync version number', action='version', version=__version__) # Read a set of arguments args = parser.parse_args() DEBUG = args.debug CONFIG_FILE = args.config_file INIT = args.init # Set Logging Level if DEBUG: for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) logging.basicConfig(level=logging.DEBUG, format=FORMAT) logger.debug('Config file: {0}'.format(CONFIG_FILE)) if INIT: logger.info('Generate a template setting.json') with open('settings_default.json', 'w') as f: f.writelines(json.dumps(DEFAULT_SETTING, indent=4)) sys.exit() # Load config try: logger.debug('Load config...') config = load_config(CONFIG_FILE) repo_dir = config['repo_dir'] files_mapping = config['files'] dirs_mapping = config['dirs'] ignore_files = config['ignore']['patterns'] ignore_files.extend(IGNORE_PATTERNS) ignore_files = sorted(list(set(ignore_files))) except Exception as error: logger.error('Can\'t load config: {0}'.format(error)) sys.exit(1) # Read and check repo has been initialized logger.debug('Trying to read repo...') try: repo = Repo(repo_dir) remote = Remote(repo, 'origin') if not remote.exists(): logger.error( 'Can\'t find \'origin\' remote url. Please set a \'origin\' remote and upstream branch at first to proceed!' ) sys.exit(1) logger.debug('Repo has been loaded successfully') logger.info('Pulling from repo...') remote.pull() except InvalidGitRepositoryError as error: logger.error('Invalid repo. Please check it again!') sys.exit(1) except NoSuchPathError as error: logger.error( 'No directory \'.git\' found. Did you initialize git project?!') sys.exit(1) if repo.bare: logger.error('Repo can\'t be a bare!') sys.exit(1) # initialize runtime files/variables init_files(repo_dir, ignore_files) changed = False logger.info('Repo Initialization completed') logger.debug('Performing prechecks...') try: precheck(files_mapping.keys(), dirs_mapping.keys()) except Exception as error: logger.error('Prechecks failed!') logger.error(error) sys.exit(1) logger.debug('Perform cleanup task on repo...') clean_up_repo(files_mapping.values(), dirs_mapping.values(), repo_dir, ignore=ignore_files) logger.debug('Proceed to check file changes') logger.debug('Detect if the sync list changes...') prev_config = NO_LAST_SYNC_STATE if check_last_sync(repo_dir): logger.debug('Last sync record found!') prev_config = load_last_sync(repo_dir) # Check whether folder states are identical logger.info('Check files whether if updated') src_files_to_be_copied, src_dirs_to_be_copied, dst_files_to_be_deleted, dst_dirs_to_be_deleted = check_sync_state( prev_config, config, repo_dir) logger.debug( 'Sync state: \n\t\tFiles be copied {0}\n\t\tDirs be copied {1}\n\t\tFiles be deleted {2}\n\t\tDirs be deleted {3}' .format(src_files_to_be_copied, src_dirs_to_be_copied, dst_files_to_be_deleted, dst_dirs_to_be_deleted)) # Start to perform sync task (overwrite dst-file / delete dst-file / copy entire src-folder(src-file) to dst-folder(dst-file)) change_indicator = 0 if (dst_files_to_be_deleted): for file_path in dst_files_to_be_deleted: try: logger.debug('Deleting file {0}'.format(file_path)) delete_file(file_path) logger.debug(' ... Successfully') except Exception as error: logger.debug(' ... Failed') raise error logger.debug('Files deletion finished') change_indicator += 1 if (dst_dirs_to_be_deleted): for dir_path in dst_dirs_to_be_deleted: try: logger.debug('Deleting directory {0}'.format(dir_path)) delete_dir(dir_path) logger.debug(' ... Successfully') except Exception as error: logger.debug(' ... Failed') raise error logger.debug('Dirs deletion finished') change_indicator += 1 if (src_files_to_be_copied): for src_path, dst_path in src_files_to_be_copied.items(): try: logger.debug('Copying file {0} to {1}'.format( src_path, dst_path)) copy_file(src_path, dst_path) logger.debug(' ... Successfully') except Exception as error: logger.debug(' ... Failed') raise error logger.debug('Files addition finished') change_indicator += 1 if (src_dirs_to_be_copied): for src_path, dst_path in src_dirs_to_be_copied.items(): try: logger.debug('Copying directory {0} to {1}'.format( src_path, dst_path)) copy_dir(src_path, dst_path, ignore=ignore_files) logger.debug(' ... Successfully') except Exception as error: logger.debug(' ... Failed') raise error logger.debug('Dirs addition finished') change_indicator += 1 if change_indicator == 0: logger.info('All is up to date') sys.exit(0) logger.debug('Staging files...') logger.debug('Reset current staging') repo.index.reset() logger.info('Stage modified files into repo...') repo.git.add(A=True) logger.info('Commit to repo...') repo.index.commit('[(auto-git) leave it here for later editing]') logger.info('Push to remote origin server...') remote.push() logger.debug('Saving current sync state...') try: save_current_sync(repo_dir, config) except Exception as error: logger.error('Failed to save current sync state! {0}'.format(error)) sys.exit(1) logger.info('Finished')
def remote_repo_creator(self): remote_repo_dir = tempfile.mktemp("remote_repo_%s" % func.__name__) repo_dir = tempfile.mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) # recursive alternates info ? rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! with rw_remote_repo.config_writer() as crw: section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # Initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() base_path, rel_repo_dir = osp.split(remote_repo_dir) remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir)) with d_remote.config_writer as cw: cw.set('url', remote_repo_url) try: gd = launch_git_daemon(Git.polish_url(base_path), '127.0.0.1', GIT_DAEMON_PORT) except Exception as ex: if is_win: msg = textwrap.dedent(""" The `git-daemon.exe` must be in PATH. For MINGW, look into .\Git\mingw64\libexec\git-core\), but problems with paths might appear. CYGWIN has no daemon, but if one exists, it gets along fine (has also paths problems) Anyhow, alternatively try starting `git-daemon` manually:""" ) else: msg = "Please try starting `git-daemon` manually:" msg += textwrap.dedent(""" git daemon --enable=receive-pack --base-path=%s %s You can also run the daemon on a different port by passing --port=<port>" and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port> """ % (base_path, base_path)) raise AssertionError(ex, msg) # END make assertion else: # Try listing remotes, to diagnose whether the daemon is up. rw_repo.git.ls_remote(d_remote) # adjust working dir prev_cwd = os.getcwd() os.chdir(rw_repo.working_dir) try: return func(self, rw_repo, rw_remote_repo) except: log.info( "Keeping repos after failure: repo_dir = %s, remote_repo_dir = %s", repo_dir, remote_repo_dir) repo_dir = remote_repo_dir = None raise finally: os.chdir(prev_cwd) finally: try: log.debug("Killing git-daemon...") gd.proc.kill() except: ## Either it has died (and we're here), or it won't die, again here... pass rw_repo.git.clear_cache() rw_remote_repo.git.clear_cache() rw_repo = rw_remote_repo = None import gc gc.collect() if repo_dir: rmtree(repo_dir) if remote_repo_dir: rmtree(remote_repo_dir) if gd is not None: gd.proc.wait()
name = input(name_query) while not name: name = input(name_query) confirm_query = "Is this information correct? \n" + "Remote url: " + remote_url + "\n" + "Project name: " + name + "\n" + "(Y/N): " confirm_response = input(confirm_query).lower() while confirm_response != "y" and confirm_response != "n": confirm_response = input(confirm_query).lower() if confirm_response == "n": continue else: break # Set remote url remote = Remote(repo, "origin") remote.set_url(remote_url) # Pull submodules for submodule in repo.submodules: submodule.update(init=True) # Set project name: name = "_".join(name.split()) cmake_lists = "CMakeLists.txt" with open(cmake_lists) as f: s = f.read() with open(cmake_lists, "w") as f: replaced = s.replace("vulkan_project", name) f.write(replaced)
def remote_repo_creator(self): remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__) repo_dir = _mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) # recursive alternates info ? rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! crw = rw_remote_repo.config_writer() section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # release lock crw.release() del (crw) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost:%s%s" % (GIT_DAEMON_PORT, remote_repo_dir) d_remote.config_writer.set('url', remote_repo_url) temp_dir = osp(_mktemp()) # On windows, this will fail ... we deal with failures anyway and default to telling the user to do it try: gd = Git().daemon(temp_dir, enable='receive-pack', listen='127.0.0.1', port=GIT_DAEMON_PORT, as_process=True) # yes, I know ... fortunately, this is always going to work if sleep time is just large enough time.sleep(0.5) except Exception: gd = None # end # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError as e: # We assume in good faith that we didn't start the daemon - but make sure we kill it anyway # Of course we expect it to work here already, but maybe there are timing constraints # on some platforms ? if gd is not None: os.kill(gd.proc.pid, 15) print(str(e)) if os.name == 'nt': msg = "git-daemon needs to run this test, but windows does not have one. " msg += 'Otherwise, run: git-daemon "%s"' % temp_dir raise AssertionError(msg) else: msg = 'Please start a git-daemon to run this test, execute: git daemon --enable=receive-pack "%s"' msg += 'You can also run the daemon on a different port by passing --port=<port>' msg += 'and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port>' msg %= temp_dir raise AssertionError(msg) # END make assertion # END catch ls remote error # adjust working dir prev_cwd = os.getcwd() os.chdir(rw_repo.working_dir) try: try: return func(self, rw_repo, rw_remote_repo) except: print( "Keeping repos after failure: repo_dir = %s, remote_repo_dir = %s" % (repo_dir, remote_repo_dir), file=sys.stderr) repo_dir = remote_repo_dir = None raise finally: # gd.proc.kill() ... no idea why that doesn't work if gd is not None: os.kill(gd.proc.pid, 15) os.chdir(prev_cwd) rw_repo.git.clear_cache() rw_remote_repo.git.clear_cache() if repo_dir: shutil.rmtree(repo_dir, onerror=_rmtree_onerror) if remote_repo_dir: shutil.rmtree(remote_repo_dir, onerror=_rmtree_onerror) if gd is not None: gd.proc.wait()
def add_remote(repo, remote_name, remote_url): Remote.add(repo=repo, name=remote_name, url=remote_url)
def _push(self, origin: git.Remote): if self.git_enabled: if self.verbose: print('Pushing dot file repository') origin.push()
def clean_remote(remote: Remote): print_warning(f"Fetching {remote.name}, {remote.url}") remote.fetch() for branch in remote.refs: print(branch)
def remote_repo_creator(self): remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__) repo_dir = _mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) # recursive alternates info ? rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! with rw_remote_repo.config_writer() as crw: section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost:%s%s" % (GIT_DAEMON_PORT, remote_repo_dir) with d_remote.config_writer as cw: cw.set('url', remote_repo_url) temp_dir = osp(_mktemp()) gd = launch_git_daemon(temp_dir, '127.0.0.1', GIT_DAEMON_PORT) try: # yes, I know ... fortunately, this is always going to work if sleep time is just large enough time.sleep(0.5) # end # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError as e: # We assume in good faith that we didn't start the daemon - but make sure we kill it anyway # Of course we expect it to work here already, but maybe there are timing constraints # on some platforms ? try: gd.proc.terminate() except Exception as ex: log.debug( "Ignoring %r while terminating proc after %r.", ex, e) log.warning('git(%s) ls-remote failed due to:%s', rw_repo.git_dir, e) if is_win: msg = textwrap.dedent(""" MINGW yet has problems with paths, and `git-daemon.exe` must be in PATH (look into .\Git\mingw64\libexec\git-core\); CYGWIN has no daemon, but if one exists, it gets along fine (has also paths problems) Anyhow, alternatively try starting `git-daemon` manually:""" ) else: msg = "Please try starting `git-daemon` manually:" msg += textwrap.dedent(""" git daemon --enable=receive-pack '%s' You can also run the daemon on a different port by passing --port=<port>" and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port> """ % temp_dir) from nose import SkipTest raise SkipTest(msg) if is_win else AssertionError(msg) # END make assertion # END catch ls remote error # adjust working dir prev_cwd = os.getcwd() os.chdir(rw_repo.working_dir) try: return func(self, rw_repo, rw_remote_repo) except: log.info( "Keeping repos after failure: repo_dir = %s, remote_repo_dir = %s", repo_dir, remote_repo_dir) repo_dir = remote_repo_dir = None raise finally: os.chdir(prev_cwd) finally: try: gd.proc.kill() except: ## Either it has died (and we're here), or it won't die, again here... pass rw_repo.git.clear_cache() rw_remote_repo.git.clear_cache() rw_repo = rw_remote_repo = None import gc gc.collect() if repo_dir: rmtree(repo_dir) if remote_repo_dir: rmtree(remote_repo_dir) if gd is not None: gd.proc.wait()
def remote_repo_creator(self): remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__) repo_dir = _mktemp("remote_clone_non_bare_repo") rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) # recursive alternates info ? rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_remote_repo.daemon_export = True # this thing is just annoying ! crw = rw_remote_repo.config_writer() section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # release lock crw.release() del(crw) # initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. The daemon should be started # by the user, not by us d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() remote_repo_url = "git://localhost:%s%s" % (GIT_DAEMON_PORT, remote_repo_dir) d_remote.config_writer.set('url', remote_repo_url) temp_dir = osp(_mktemp()) # On windows, this will fail ... we deal with failures anyway and default to telling the user to do it try: gd = Git().daemon(temp_dir, enable='receive-pack', listen='127.0.0.1', port=GIT_DAEMON_PORT, as_process=True) # yes, I know ... fortunately, this is always going to work if sleep time is just large enough time.sleep(0.5) except Exception: gd = None # end # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) except GitCommandError as e: # We assume in good faith that we didn't start the daemon - but make sure we kill it anyway # Of course we expect it to work here already, but maybe there are timing constraints # on some platforms ? if gd is not None: os.kill(gd.proc.pid, 15) print(str(e)) if os.name == 'nt': msg = "git-daemon needs to run this test, but windows does not have one. " msg += 'Otherwise, run: git-daemon "%s"' % temp_dir raise AssertionError(msg) else: msg = 'Please start a git-daemon to run this test, execute: git daemon --enable=receive-pack "%s"' msg += 'You can also run the daemon on a different port by passing --port=<port>' msg += 'and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port>' msg %= temp_dir raise AssertionError(msg) # END make assertion # END catch ls remote error # adjust working dir prev_cwd = os.getcwd() os.chdir(rw_repo.working_dir) try: try: return func(self, rw_repo, rw_remote_repo) except: print("Keeping repos after failure: repo_dir = %s, remote_repo_dir = %s" % (repo_dir, remote_repo_dir), file=sys.stderr) repo_dir = remote_repo_dir = None raise finally: # gd.proc.kill() ... no idea why that doesn't work if gd is not None: os.kill(gd.proc.pid, 15) os.chdir(prev_cwd) rw_repo.git.clear_cache() rw_remote_repo.git.clear_cache() if repo_dir: shutil.rmtree(repo_dir, onerror=_rmtree_onerror) if remote_repo_dir: shutil.rmtree(remote_repo_dir, onerror=_rmtree_onerror) if gd is not None: gd.proc.wait()
def update(remote: git.Remote, branch: str) -> None: """Update given remote by pushing the given branch.""" print(f'pushing {branch}!') remote.push(f'origin/{branch}:refs/heads/{branch}')
def git_check(wdir='.'): git_root = git_rootdir(wdir) if git_root == None: return 0 f = "{}/.git/FETCH_HEAD".format(os.path.abspath(git_root)) if os.path.isfile(f): ''' make sure this is not a freshly cloned repo with no FETCH_HEAD ''' last_fetch = int(os.stat(f).st_mtime) diff = int(time.time() - last_fetch) else: # if the repo is a fresh clone, there is no FETCH_HEAD # so set time diff to more than a minute to force a fetch diff = 61 repo = Repo(git_root) assert not repo.bare remote_names = [] # fetch at most once per minute for r in repo.remotes: remote_names.append(r.name) if diff > 60: remote = Remote(repo, r.name) remote.fetch() # check what branch we're on branch = repo.active_branch.name origin_branch = None for ref in repo.git.branch('-r').split('\n'): for rn in remote_names: if "{}/{}".format(rn, branch) in ref: origin_branch = ref.strip() break if origin_branch == None: # no remote branch to compare to return 0 # check if local branch is ahead and /or behind remote branch command = "git -C {} rev-list --left-right --count \"{}...{}\"".format( git_root, branch, origin_branch) #print command (ahead_behind, err, exitcode) = run(command, raise_exception_on_fail=True) ahead_behind = ahead_behind.strip().split("\t") ahead = int(ahead_behind[0]) behind = int(ahead_behind.pop()) if behind > 0: sys.stderr.write("") sys.stderr.write( "GIT ERROR: You are on branch {} and are behind the remote. Please git pull and/or merge before proceeding. Below is a git status:" .format(branch)) sys.stderr.write("") (status, err, exitcode) = run("git -C {} status ".format(git_root)) sys.stderr.write(status) sys.stderr.write("") return (-1) else: TB_GIT_DEFAULT_BRANCH = os.getenv('TB_GIT_DEFAULT_BRANCH', 'master') if branch != TB_GIT_DEFAULT_BRANCH: ''' in this case assume we're on a feature branch if the FB is behind master then issue a warning ''' command = "git -C {} branch -vv | grep {} ".format( git_root, TB_GIT_DEFAULT_BRANCH) (origin_master, err, exitcode) = run(command) if exitcode != 0: ''' In this case the git repo does not contain TB_GIT_DEFAULT_BRANCH, so I guess assume that we're on the default branch afterall and that we're up to date persuant to the above code ''' return 0 for line in origin_master.split("\n"): if line.strip().startswith(TB_GIT_DEFAULT_BRANCH): origin = line.strip().split('[')[1].split('/')[0] assert origin != None command = "git -C {} rev-list --left-right --count \"{}...{}/{}\"".format( git_root, branch, origin, TB_GIT_DEFAULT_BRANCH) (ahead_behind, err, exitcode) = run(command) ahead_behind = ahead_behind.strip().split("\t") ahead = int(ahead_behind[0]) behind = int(ahead_behind.pop()) command = "git -C {} rev-list --left-right --count \"{}...{}\"".format( git_root, branch, TB_GIT_DEFAULT_BRANCH) (ahead_behind, err, exitcode) = run(command) ahead_behind = ahead_behind.strip().split("\t") local_ahead = int(ahead_behind[0]) local_behind = int(ahead_behind.pop()) if behind > 0: sys.stderr.write("") sys.stderr.write( "GIT WARNING: Your branch, {}, is {} commit(s) behind {}/{}.\n" .format(branch, behind, origin, TB_GIT_DEFAULT_BRANCH)) sys.stderr.write( "This action may clobber new changes that have occurred in {} since your branch was made.\n" .format(TB_GIT_DEFAULT_BRANCH)) sys.stderr.write( "It is recommended that you stop now and merge or rebase from {}\n" .format(TB_GIT_DEFAULT_BRANCH)) sys.stderr.write("\n") if ahead != local_ahead or behind != local_behind: sys.stderr.write("") sys.stderr.write( "INFO: your local {} branch is not up to date with {}/{}\n" .format(TB_GIT_DEFAULT_BRANCH, origin, TB_GIT_DEFAULT_BRANCH)) sys.stderr.write("HINT:") sys.stderr.write( "git checkout {} ; git pull ; git checkout {}\n". format(TB_GIT_DEFAULT_BRANCH, branch)) sys.stderr.write("\n") answer = raw_input( "Do you want to continue anyway? [y/N]? ").lower() if answer != 'y': log("") log("Aborting due to user input") exit() return 0
def remote_repo_creator(self): rw_daemon_repo_dir = tempfile.mktemp(prefix="daemon_repo-%s-" % func.__name__) rw_repo_dir = tempfile.mktemp(prefix="daemon_cloned_repo-%s-" % func.__name__) rw_daemon_repo = self.rorepo.clone(rw_daemon_repo_dir, shared=True, bare=True) # recursive alternates info ? rw_repo = rw_daemon_repo.clone(rw_repo_dir, shared=True, bare=False, n=True) try: rw_repo.head.commit = working_tree_ref rw_repo.head.reference.checkout() # prepare for git-daemon rw_daemon_repo.daemon_export = True # this thing is just annoying ! with rw_daemon_repo.config_writer() as crw: section = "daemon" try: crw.add_section(section) except Exception: pass crw.set(section, "receivepack", True) # Initialize the remote - first do it as local remote and pull, then # we change the url to point to the daemon. d_remote = Remote.create(rw_repo, "daemon_origin", rw_daemon_repo_dir) d_remote.fetch() base_daemon_path, rel_repo_dir = osp.split(rw_daemon_repo_dir) remote_repo_url = Git.polish_url( "git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir)) with d_remote.config_writer as cw: cw.set('url', remote_repo_url) with git_daemon_launched( Git.polish_url( base_daemon_path, is_cygwin=False), # No daemon in Cygwin. '127.0.0.1', GIT_DAEMON_PORT): # Try listing remotes, to diagnose whether the daemon is up. rw_repo.git.ls_remote(d_remote) with cwd(rw_repo.working_dir): try: return func(self, rw_repo, rw_daemon_repo) except: log.info( "Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s", rw_repo_dir, rw_daemon_repo_dir) rw_repo_dir = rw_daemon_repo_dir = None raise finally: rw_repo.git.clear_cache() rw_daemon_repo.git.clear_cache() del rw_repo del rw_daemon_repo gc.collect() gitdb.util.mman.collect() gc.collect() if rw_repo_dir: rmtree(rw_repo_dir) if rw_daemon_repo_dir: rmtree(rw_daemon_repo_dir)
def is_same_commit(repo: Repo, remote: Remote) -> bool: local_commit = repo.commit() remote_commit = remote.fetch()[0].commit return local_commit.hexsha == remote_commit.hexsha
def push_repo_to_remotes(repo, remotes): for name, remote in remotes: r = Remote.add(repo, name, remote) r.push("master") logging.info("Base repo pushed to all student repos")
def test_analyze_pr(tmp_path: Path, mock_push: Mock) -> None: runner = CliRunner() repo = Repo.init(str(tmp_path)) Remote.create(repo, "origin", "https://github.com/foo/bar") src = (Path(__file__).parent / "data" / "kubernetes" / "gafaelfawr" / "Chart.yaml") dst = tmp_path / "Chart.yaml" shutil.copy(src, dst) repo.index.add(str(dst)) actor = Actor("Someone", "*****@*****.**") repo.index.commit("Initial commit", author=actor, committer=actor) sqre = dict_to_yaml({"entries": {"gafaelfawr": [{"version": "1.4.0"}]}}) payload = {"name": "Someone", "email": "*****@*****.**"} created_pr = False def check_pr_post(url: str, **kwargs: Any) -> CallbackResult: change = "Update gafaelfawr Helm chart from 1.3.1 to 1.4.0" assert json.loads(kwargs["data"]) == { "title": CommitMessage.title, "body": f"- {change}\n", "head": "u/neophile", "base": "master", "maintainer_can_modify": True, "draft": False, } assert repo.head.ref.name == "u/neophile" yaml = YAML() data = yaml.load(dst) assert data["dependencies"][0]["version"] == "1.4.0" commit = repo.head.commit assert commit.author.name == "Someone" assert commit.author.email == "*****@*****.**" assert commit.message == f"{CommitMessage.title}\n\n- {change}\n" nonlocal created_pr created_pr = True return CallbackResult(status=201) with aioresponses() as mock: mock.get("https://lsst-sqre.github.io/charts/index.yaml", body=sqre) mock.get("https://api.github.com/user", payload=payload) mock.get( "https://api.github.com/repos/foo/bar", payload={"default_branch": "master"}, ) pattern = re.compile(r"https://api.github.com/repos/foo/bar/pulls\?.*") mock.get(pattern, payload=[]) mock.post( "https://api.github.com/repos/foo/bar/pulls", callback=check_pr_post, ) result = runner.invoke( main, ["analyze", "--path", str(tmp_path), "--pr"], env={"NEOPHILE_CACHE_ENABLED": "0"}, ) assert created_pr assert result.exit_code == 0 assert mock_push.call_args_list == [ call("u/neophile:u/neophile", force=True) ] assert repo.head.ref.name == "master"