Exemplo n.º 1
0
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()
Exemplo n.º 2
0
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
Exemplo n.º 3
0
        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)
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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')