Example #1
0
def init(req):
	print "args:", req.args, req.args.path
	repo_path = os.path.join(req.args.path,'.git')
	if not os.path.isdir(repo_path):
		raise Abort("no repository found in '%s' (.git not found)!" % (os.path.abspath(req.args.path)))
	repo = Repository(req.args.path)
	print "repo references:", repo.listall_references()
	xxl_path = os.path.join(req.args.path,'.gitxxl')
	if os.path.exists(xxl_path):
		print "reinitializing existing XXL repo"
	else:
		print "initialiling XXL repo"
		os.mkdir(xxl_path)
		
	#install commit hooks
	dst = os.path.join(repo_path,"hooks","pre-commit")
	if not os.path.isfile(dst):
		src = os.path.join(sys.exec_prefix,"dist","hooks","pre-commit")
		print "installing pre-commit hook from:", src
		shutil.copyfile(src, dst)
		perm = os.stat(dst)
		os.chmod(dst,perm.st_mode | stat.S_IXUSR)

	dst = os.path.join(repo_path,"hooks","post-commit")
	if not os.path.isfile(dst):
		src = os.path.join(sys.exec_prefix,"dist","hooks","post-commit")
		print "installing post-commit hook from:", src
		shutil.copyfile(src, dst)
		perm = os.stat(dst)
		os.chmod(dst,perm.st_mode | stat.S_IXUSR)
Example #2
0
    def install_package(self, pkg_name, expression):
        package_cache_path = path.join(APP_CACHE_DIR, pkg_name)

        # Check if the package is cached
        try:
            repo = Repository(package_cache_path)

            # TODO: check lastest version
            # If lastest is cached, advance
            # If no, prompt user
        except KeyError as e:
            repo = clone_repository(APP_REMOTE['url'], package_cache_path)

        # Get suitable version for the expression
        versions = utils.get_versions_cached(repo)
        version = max_satisfy(versions=versions.keys(), expression='')

        package_archive_name = '{0}-{1}.tar'.format(pkg_name, version)
        package_archive_path = path.join(APP_ARCHIVE_DIR, package_archive_name)

        # Create archive file
        # If the file already exists, move forward
        if path.isfile(package_archive_path):
            with tarfile.open(package_archive_path, 'w') as archive:
                repo.write_archive(archive=archive, treeish=versions[version].tree_id)

        # TODO: use strategy
        # Extract archive to package dir
        path_to_package = path.join(USER_PACKAGE_FOLDER, 'user', pkg_name)
        tar = tarfile.open(package_archive_path)
        tar.extractall(path=path_to_package)
        tar.close()
def extract_commits(repos_root, output_path):
    # Uncomment code to generate a separate file for each commit.

    try:
        os.makedirs(output_path)
    except FileExistsError as ex:
        pass

    exec_dir = os.getcwd()

    for git_repo in get_immediate_subdirectories(repos_root):
        os.chdir(git_repo)
        repo = Repository(os.path.join(git_repo, git_folder))
        root = etree.Element("commits")

        repo_name = os.path.basename(os.path.normpath(git_repo))

        print("\n> project: " + repo_name + " extraction started")

        for commit in repo.walk(repo.head.target):
            stats = get_commit_stats(commit.id)
            commit_xml = commit_to_xml(commit, stats)
            root.append(commit_xml)

            # print(".", end=" ")
            print("> project: " + repo_name + ", commit " + str(commit.id) + " processed")

        output_xml = xml_to_string(root)

        os.chdir(exec_dir)

        with open(os.path.join(output_path, repo_name + "_" + output_commit_file), "w") as file:
            file.write(output_xml)

        print("\n> project: " + repo_name + " extraction finished")
Example #4
0
def commit_new_tickets_to_git(queue, repo_path):
    global last_push_ts
    #repo
    repo = Repository(os.path.join(repo_path, '.git'))
    index = repo.index
    author = Signature('yourname', 'youremail')
    while True:
        #write tickets into file
        ticket = queue.get(block=True)
        #filename format is yyyy-mm-dd
        d = datetime.utcnow().date()
        filename = '%s.txt' % d.strftime('%Y-%m-%d')
        f = open(os.path.join(repo_path, filename), 'ab')
        f.write('%s\n' % ticket.toJson())
        f.close()
        #commit
        index.add(filename)
        index.write()
        oid = index.write_tree()
        repo.create_commit('HEAD', author, author, ticket.toJson(), oid, [repo.head.oid])
        #push
        d_ts = datetime.utcnow()
        if last_push_ts is None or d_ts > (last_push_ts + timedelta(seconds = 60)):
            push_to_github(repo_path)
            last_push_ts = datetime.utcnow()
class Repo(object):
  def __init__(self,path,username,password):
    self.repo = Repository(path)
    self.username = username
    self.password = password
    self.path=path

  def commit(self,file,refspec,email,author_username,message):
    self.repo.index.add(file)
    index = self.repo.index
    index.write()
    tree = self.repo.index.write_tree()
    author = Signature(author_username,email)
    self.repo.create_commit(refspec,
        author,
        author,message,tree, [self.repo.head.get_object().hex] )

  def commit_fallback(self,message):
    return subprocess.check_output(["git","commit","-m",message],cwd=self.path)

  def push(self,refspec):
    credentials = UserPass(self.username,self.password)
    remoteCall = RemoteCallbacks(credentials)
    remo = self.repo.remotes["origin"]
    remo.push(refspec,remoteCall)
Example #6
0
def get_new_articles():
    blog = PelicanBlog()
    content_dir = blog.get_content_directory()
    repo = Repository(os.path.abspath(os.path.dirname(__file__)))
    diff = repo.revparse_single("HEAD").tree.diff_to_tree()
    existing_articles = set(os.path.relpath(obj.old_file_path, content_dir)
                            for obj in diff
                            if obj.old_file_path.startswith(content_dir))
    all_articles = set(blog.get_posts())
    new_articles = {art for art in all_articles - existing_articles
                    if blog.get_post_lang(art) in (TWITTER_LANGUAGE, "")}
    new_titles = []
    repo.index.read()
    for newart in new_articles:
        title = blog.get_post_title(newart)
        yield Article(title, blog.get_post_url(newart),
                      blog.get_post_authors(newart))
        new_titles.append(title)
        repo.index.add(os.path.join(content_dir, newart))
    blogger = Signature(repo.config["user.name"], repo.config["user.email"])
    repo.create_commit("HEAD", blogger, blogger,
                       "[BLOG] %s" % ", ".join(new_titles),
                       repo.index.write_tree(), [repo.head.peel().oid])
    repo.index.write()
    # TODO(v.markovtsev): implement git push using pygit2
    subprocess.call(("git", "push", "origin", repo.head.shorthand))
Example #7
0
class GitRepositoryTestCase(unittest.TestCase):

    def setUp(self):
        self.repo_path = mkdtemp()
        init_repository(self.repo_path, False)
        self.repo = Repository(self.repo_path)

    def tearDown(self):
        try:
            rmtree(self.repo_path)
        except:
            pass

    def test_create_repo(self):
        repo_path = mkdtemp()
        try:
            GitRepository.create_repo(repo_path)
            for f in [os.path.join('content', 'attachments', 'mercurial.png'),
                      os.path.join('content', 'post', 'example-post.rst'),
                      os.path.join('content', 'post', 'lorem-ipsum.rst'),
                      os.path.join('content', 'about.rst'),
                      os.path.join('static', 'screen.css'),
                      os.path.join('templates', 'base.html'),
                      os.path.join('templates', 'posts.html'),
                      os.path.join('templates', 'post_list.html'),
                      'config.yaml', '.gitignore', '.git']:
                self.assertTrue(os.path.exists(os.path.join(repo_path, f)),
                                'Not found: %s' % f)
        finally:
            rmtree(repo_path)

    def test_get_changectx_rev_default(self):
        git_repo = GitRepository(self.repo_path)
        with codecs.open(os.path.join(self.repo_path, 'foo.rst'), 'w',
                         encoding='utf-8') as fp:
            fp.write('foo')
        sign = Signature('foo', '*****@*****.**')
        tree = self.repo.TreeBuilder().write()
        self.repo.index.add('foo.rst')
        self.repo.create_commit('refs/heads/master', sign, sign, 'foo', tree,
                                [])
        self.assertTrue(isinstance(git_repo.get_changectx(REVISION_DEFAULT),
                                   ChangeCtxDefault),
                        'changectx object is not an instance of '
                        'ChangeCtxDefault')

    def test_get_changectx_rev_working_dir(self):
        git_repo = GitRepository(self.repo_path)
        with codecs.open(os.path.join(self.repo_path, 'foo.rst'), 'w',
                         encoding='utf-8') as fp:
            fp.write('foo')
        sign = Signature('foo', '*****@*****.**')
        tree = self.repo.TreeBuilder().write()
        self.repo.index.add('foo.rst')
        self.repo.create_commit('refs/heads/master', sign, sign, 'foo', tree,
                                [])
        self.assertTrue(
            isinstance(git_repo.get_changectx(REVISION_WORKING_DIR),
                       ChangeCtxWorkingDir),
            'changectx object is not an instance of ChangeCtxWorkingDir')
    def get_commit_activity(self, project):
        from datetime import date, timedelta
        from pygit2 import Repository
        from pygit2 import GIT_SORT_TIME
        repo = Repository(project.gitrepo)

        weeks = self.get_weeks()
        for commit in repo.walk(repo.head.oid, GIT_SORT_TIME):
            commit_time = date.fromtimestamp(commit.commit_time)
            commit_week = commit_time - timedelta(days=commit_time.weekday())

            if commit_week not in weeks:
                continue

            weeks[commit_week]['mine'] += 1

        counts = []
        max = 0
        for k in sorted(weeks.iterkeys()):
            counts.append({
                "week":     k.isoformat(),
                "mine":     weeks[k]['mine'],
                "others":   weeks[k]['others'],
            })
        return counts
def get_bug_commit_ratio_per_file(git_folder = ".git/", output_file):
    result = []
    exec_dir = os.getcwd()
    repo = Repository(os.path.join(git_repo, git_folder))

    os.chdir(git_repo)

    for commit in repo.walk(repo.head.target):
        touched_files = get_touched_files(commit)

        for file in touched_files:
            file_data = [f for f in result if f['file_name'] == file]

            if file_data:
                file_data = file_data[0]
                file_data['commit_num'] += 1
                if bug_related:
                    file_data['bug_commit_num'] += 1
            else:
                result.append({'file_name': file,
                               'commit_num': 1,
                               'bug_commit_num': 1 if bug_related else 0})

    os.chdir(exec_dir)

    for entry in result:
        entry['bug_commit_ratio'] = entry['bug_commit_num'] / entry['commit_num']

    with open(output_file, "w", newline='') as output:
        writer = csv.DictWriter(output, csv_header)
        writer.writeheader()
        writer.writerows(result)
Example #10
0
def getHist(repo):
	base = Repository(repo)
	base.checkout('HEAD')
	history = []
	for commit in base.walk(base.head.target, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE):
		history.append(commit)
	
	return history
def get_blame_test():
    git_repo = "/Users/aniketp/Workspace/Capstone/Source/eclipse/eclipse.platform.runtime"
    sample_file = "bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java"
    exec_dir = os.getcwd()
    repo = Repository(os.path.join(git_repo, git_folder))
    os.chdir(git_repo)
    
    blameObj = repo.blame(sample_file, min_line=1, max_line=20)
Example #12
0
def get_and_update_repo_cache(repo_path):
    cache_filename = '%s-stats.cache' % repo_path
    if os.path.exists(cache_filename):
        with open(cache_filename) as f:
            data = load(f)
    else:
        data = {
            'author_to_month_to_additions': defaultdict(defaultdict_int),
            'author_to_month_to_deletions': defaultdict(defaultdict_int),
            'author_to_month_to_commits': defaultdict(defaultdict_int),
            'day_to_count': defaultdict(defaultdict_int),
            'latest_sha': None,
        }

    repo = Repository(repo_path)

    count = 0
    for commit in repo.walk(repo.head.target, GIT_SORT_TOPOLOGICAL):
        count += 1
        if commit.type == GIT_OBJ_COMMIT:
            if data['latest_sha'] == commit.hex:
                break
        
            if not commit.message.lower().startswith('merge'):
                try:
                    d = repo.diff('%s^' % commit.hex, commit)
                except KeyError:
                    # First commit!
                    break
                patches = list(d)
                additions = sum([p.additions for p in patches])
                deletions = sum([p.deletions for p in patches])

                author = author_aliases.get(commit.author.email, commit.author.email)

                day = date.fromtimestamp(commit.commit_time)
                data['day_to_count']['Lines'][day] += additions
                data['day_to_count']['Lines'][day] -= deletions

                if additions > 1000 and deletions < 5 and commit.hex not in whitelist_commits:
                    if commit.hex not in blacklist_commits:
                        print 'WARNING: ignored %s looks like an embedding of a lib (message: %s)' % (commit.hex, commit.message)
                    continue
                if (additions > 3000 or deletions > 3000) and commit.hex not in whitelist_commits:
                    if commit.hex not in blacklist_commits and additions != deletions:  # Guess that if additions == deletions it's a big rename of files
                        print 'WARNING: ignored %s because it is bigger than 3k lines. Put this commit in the whitelist or the blacklist (message: %s)' % (commit.hex, commit.message)
                    continue
                month = date(day.year, day.month, 1)
                data['author_to_month_to_additions'][author][month] += additions
                data['author_to_month_to_deletions'][author][month] += deletions
                data['author_to_month_to_commits'][author][month] += 1
                if data['latest_sha'] is None:
                    data['latest_sha'] = commit.hex

    with open(cache_filename, 'w') as f:
        dump(data, f)

    return data
Example #13
0
    def gets(cls, path, max_count=100, order=GIT_SORT_TIME):
        """gets commits from a git repository.

        :param path: The normalized path to the git repository.
        :param max_count: max count of commits.
        :param order: order commits list."""
        repo = Repository(path)
        return [cls(c.hex, [p.hex for p in c.parents])
                for c in islice(repo.walk(repo.head.target, order),
                                max_count)]
Example #14
0
def sync_handler(fork_from: str, from_sha: str, repo_name: str,
                 ticket_id: int, pr_url: str):
    output_path = '{}.txt'.format(pr_url.split('/', 3)[3].rsplit('/', 2)[0])
    output_path = os.path.join(WORK_DIR, output_path.replace('/', '_'))
    work_tree = os.path.join(WORK_DIR, fork_from)
    parent_path = os.path.dirname(work_tree)
    if not os.path.exists(parent_path):
        os.makedirs(parent_path)
    if not os.path.exists(work_tree):
        repo = clone_repository(
            '{0}{1}.git'.format(GITHUB_URL, fork_from), work_tree)
    else:
        repo = Repository(work_tree)

    remote_name = repo_name.split('/')[0]
    update_remote(work_tree, repo, repo_name, remote_name)

    if remote_name == 'origin':
        commit = repo.revparse_single(from_sha)
        repo.checkout_tree(commit, strategy=GIT_CHECKOUT_FORCE)
    else:
        ref_name = 'refs/pull/{0}/head'.format(ticket_id)
        try:
            repo.create_reference(ref_name, from_sha)
        except ValueError:
            pass
        ref = repo.lookup_reference(ref_name)
        repo.checkout(ref, strategy=GIT_CHECKOUT_FORCE)
    cwd = os.getcwd()
    os.chdir(work_tree)
    subprocess.call(
        '{} . --output-file={}'.format(FLAKE8_EXECUTABLE, output_path),
        shell=True)
    os.chdir(cwd)
    return output_path
Example #15
0
def commitInfo(repo, history):
	# GET A REPO ON DISK
	base = Repository(repo)
	base.checkout('HEAD')

	# MOVE THROUGH THE SYSTEM HISTORY FROM NEWEST TO OLDEST COMMIT
	for commit in history:
		print 'Date/Time: ' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(commit.commit_time))
		print 'Comment Hex: ' + commit.hex
		print 'Message: ' + commit.message.rstrip('\n')
		print ''
Example #16
0
    def __init__(self):
        pubsub = PubSub()
        events_dispatcher = EventsDispatcher(pubsub)
        display = self.display_surface()
        repo = Repository(config["repo_path"])
        branches = repo.listall_branches()
        drawer = Drawer(repo, branches, display, pubsub)

        pubsub.sub("on_program_exit", self.exit_program)

        self.main_loop = MainLoop(display, drawer, events_dispatcher)
        self.init_screen()
Example #17
0
def get_deleted_files(path_to_repository):
    """Utility method for getting the deleted files from a Git repository.

        Args:
            path_to_repository (str): Path to the Git repository

        Returns:
            List(str): List of filenames of all deleted files in the provided repository.
    """
    repo = Repository(path_to_repository)
    status_entries = repo.status()
    return [path for path, st in status_entries.items() if st & _STATI_DELETED]
Example #18
0
def get_changed_files(path_to_repository):
    """Utility method for getting the currently changed files from a Git repository.

        Args:
            path_to_repository (str): Path to the Git repository

        Returns:
            List(str): List of filenames of all changed files in the provided repository.
    """
    repo = Repository(path_to_repository)
    status_entries = repo.status()
    return [path for path, st in status_entries.items() if st & _STATI_CONSIDERED_FOR_PRECOMMIT]
Example #19
0
def get_current_timestamp(path_to_repository):
    """Utility method for getting the timestamp of the last commit from a Git repository.

        Args:
            path_to_repository (str): Path to the Git repository

        Returns:
            str: The timestamp of the last commit in the provided repository.
    """
    repo = Repository(path_to_repository)
    head = repo.revparse_single('HEAD')
    return head.commit_time
Example #20
0
def get_current_branch(path_to_repository):
    """Utility method for getting the current branch from a Git repository.

        Args:
            path_to_repository (str): Path to the Git repository

        Returns:
            str: The current branch in the provided repository.
    """
    repo = Repository(path_to_repository)
    head = repo.lookup_reference("HEAD").resolve()
    return head.shorthand
def get_churn_per_commit(git_repo, output_file):
    touched_files = []
    exec_dir = os.getcwd()
    repo = Repository(os.path.join(git_repo, git_folder))
    os.chdir(git_repo)

    for commit in repo.walk(repo.head.target):
        touched_files = get_touched_files(commit)

    with open(output_file, "w", newline='') as output:
        writer = csv.DictWriter(output, csv_header)
        writer.writeheader()
        writer.writerows(touched_files)
Example #22
0
def shift(amount, repo_path):
    repo = Repository(repo_path)
    head = repo.lookup_reference('HEAD').resolve()
    adder = partial(add, amount=amount)
    changelog = dict()
    reference = REF_FMT.format(time=time(), pid=getpid())
    for commit in repo.walk(head.oid, GIT_SORT_REVERSE | GIT_SORT_TOPOLOGICAL):
        newmsg, nsubs = ISSUE_RE.subn(adder, commit.message)
        if nsubs != 0 or any(pnt.oid in changelog for pnt in commit.parents):
            parents = [changelog.get(c.oid, c.oid) for c in commit.parents]
            new_oid = repo.create_commit(reference, commit.author,
                    commit.committer, newmsg, commit.tree.oid, parents)
            changelog[commit.oid] = new_oid
    return changelog, reference
Example #23
0
class Git(object):
    r"""
    Interact with a git repository.
    """

    def __init__(self, gitdir):
        r"""
        Take a path to the git repository. Other methods interact with
        this git repository.
        """
        self.repo = Repository(gitdir)

    def branches(self):
        r"""
        Return the list of a branch name and its last commit id.
        """
        return self._refs('heads')

    def tags(self):
        r"""
        Return the list of a tag name and its last commit id.
        """
        return self._refs('tags')

    def _refs(self, type):
        refs = {}
        pattern = re.compile(r'refs/%s/(.*)$' % type)
        for ref in self.repo.listall_references():
            m = pattern.match(ref)
            if m:
                reference = self.repo.lookup_reference(ref)
                refs[m.group(1)] = reference.hex
        return refs

    def create_branch(self, name, target):
        r"""
        Create new branch.
        """
        if not is_valid_value(name):
            raise InvalidParamException("name is required")
        if not is_valid_hex(target):
            raise InvalidParamException("target is required")

        target = sha_hex2bin(target)
        try:
            self.repo.create_reference('refs/heads/%s' % name, target)
        except Exception, e:
            raise InvalidParamException(str(e))

        return True
Example #24
0
def update_repo(reponame):
    """ For a given path to a repo, pull/rebase the last changes if
    it can, add/remove/commit the new changes and push them to the
    remote repo if any.

    :kwarg reponame, full path to a git repo.
    """
    LOG.info('Processing %s' % reponame)
    if not os.path.exists(reponame):
        raise GitSyncError(
            'The indicated working directory does not exists: %s' %
            reponame)
    try:
        repo = Repository(reponame)
    except Exception as err:
        print(err)
        raise GitSyncError(
            'The indicated working directory is not a valid git '
            'repository: %s' % reponame)

    index = repo.index
    dopush = False
    origin = None

    index = repo.index
    ## Add or remove to staging the files according to their status
    if repo.status:
        status = repo.status()
        for filepath, flag in status.items():
            if flag == GIT_STATUS_WT_DELETED:
                msg = 'Remove file %s' % filepath
                LOG.info(msg)
                index.remove(filepath)
                docommit(repo, index, msg)
                dopush = True
            elif flag == GIT_STATUS_WT_NEW:
                msg = 'Add file %s' % filepath
                LOG.info(msg)
                index.add(filepath)
                docommit(repo, index, msg)
                dopush = True
            elif flag == GIT_STATUS_WT_MODIFIED:
                msg = 'Change file %s' % filepath
                LOG.info(msg)
                index.add(filepath)
                docommit(repo, index, msg)
                dopush = True

    return dopush
def get_commit_churn(repo_path):
    exec_dir = os.getcwd()
    repo = Repository(os.path.join(repo_path, git_folder))
    os.chdir(repo_path)

    debt_commits = get_debt_commits(repo_path) #commit, commit_ts, fiel_path
    file_churn = []

    for commit in repo.walk(repo.head.target):
        print (commit.id)
        curr_commit_ts = int(str(get_unix_timestamp(str(commit.id))).replace("\n", ""))
        debt_commit_flag = [f for f in debt_commits if f['commit'] == str(commit.id)]
        #print (str(debt_commit_flag))
        is_debt_commit = 0
        if debt_commit_flag:
            is_debt_commit = 1

        touched_files = get_touched_files(commit)
        for strFileChurn in touched_files:
            added_lines, deleted_lines, file_name = strFileChurn.split("\t")

            file_commit_flag = [f for f in debt_commits if f['file_path'] == file_name]
            is_file_debt = 0
            if file_commit_flag:
                file_commit_flag = file_commit_flag[0]
                debt_commit_commit_ts = int(file_commit_flag['commit_ts'])
                
                if curr_commit_ts >= debt_commit_commit_ts:
                    is_file_debt = 1

            try:
                file_churn.append({
                    'commit':str(commit.id),
                    'commit_ts':curr_commit_ts,
                    'file_name':file_name,
                    'added_lines':added_lines,
                    'deleted_lines':deleted_lines,
                    'commit_debt':is_debt_commit,
                    'file_debt':is_file_debt,
                    })
            except (AttributeError):
                continue;

    os.chdir(exec_dir)
    with open(output_file, "w", newline='') as output:
        writer = csv.DictWriter(output, csv_header)
        writer.writeheader()
        writer.writerows(file_churn)
def main():
    contrib_data_dir = sys.argv[1]
    git_repo = sys.argv[2]
    output_file = sys.argv[3]

    result = []
    exec_dir = os.getcwd()

    for contrib_file in os.listdir(contrib_data_dir):

        release = contrib_file[len(contrib_file_prefix):][:-len(contrib_file_extension)]
        contrib_file = os.path.join(contrib_data_dir, contrib_file)

        top_devs = {}

        with open(contrib_file, newline="") as csv_file:
            for row in csv.DictReader(csv_file):
                top_dev = row['top_single_dev_contribution_knowledge'].split(":")[0]

                if top_dev in top_devs:
                    top_devs[top_dev] += 1
                else:
                    top_devs[top_dev] = 1

        os.chdir(git_repo)
        call(["git", "checkout", "tags/" + release])
        os.chdir(exec_dir)

        for top_dev in top_devs:
            author_commit_count = 0
            commit_count = 0

            repo = Repository(os.path.join(git_repo, git_folder))
            for commit in repo.walk(repo.head.target):
                commit_count += 1
                if commit.author.name == top_dev:
                    author_commit_count += 1

            result.append({'release': release,
                           'release_commits': commit_count,
                           'top_dev': top_dev,
                           'files_owned': top_devs[top_dev],
                           'dev_commits': author_commit_count})

    with open(output_file, 'w', newline='') as output:
        writer = csv.DictWriter(output, csv_header)
        writer.writeheader()
        writer.writerows(result)
Example #27
0
class RepositoryProcessor(object):

    def __init__(self, repository_path):
        self.repo = GitRepository(repository_path + '/.git')
        self.users = {}

    def get_bages_processors_for_user(self, email):
        if email in self.users:
            return self.users[email]
        self.users[email] = []
        for badge_class in initialize_badge_classes():
            logging.info(u'Initializing badge class [%s] for user [%s]' % (str(badge_class), email))
            self.users[email].append(badge_class(email))
        return self.users[email]

    def process(self):
        # returns the json of the collaborators
        for commit in [c for c in self.repo.walk(self.repo.head.oid, GIT_SORT_TIME)][::-1]:
            for badge in self.get_bages_processors_for_user(commit.author.email):
                badge.process_commit(commit, datetime.fromtimestamp(commit.commit_time))
        result = []
        for user_email, badges in self.users.items():
            user = {"email": user_email, "badges": []}
            result.append(user)
            for badge in badges:
                if isinstance(badge, Badge):
                    if badge.award_this():
                        user['badges'].append({"badge_slug": badge.slug})
                else:
                    user.update(badge.update_data())
            user.update(count_modifications_by_user(user_email, self.repo.path))
            print user
        return result
Example #28
0
File: git.py Project: cholin/gix
class GitObjectRenderer:
    def __init__(self, reponame, cache, revspec, path):
        self.repo = Repository(reponame)
        self.revspec = revspec
        self.path = path
        self.object_map = {
            Blob : self._render_blob,
            Commit : self._render_commit,
            Tag : self._render_tag
        }
        self.cache = cache


    def _render_blob(self, rev):
        data = rev.data.decode('utf-8', errors='ignore')
        formatter = HtmlFormatter(linenos='inline')
        lexer = guess_lexer(data)
        blob = highlight(data, lexer, formatter)
        return render_template("objects/blob.html",
                  repo = self.repo,
                  revspec = 'master', blob = blob, path = self.path)

    def _render_commit(self, rev):
        entries = self.repo[rev.tree[self.path].oid] if self.path else rev.tree
        cached = []
        for entry in entries:
            cache_id = "{0}-commit-{1}".format(self.repo.get_name(), entry.hex)
            hit = self.cache.get(cache_id)
            if hit is not None:
                cached.append((entry, hit))
            else:
                cached.append((entry, None))

        files = sorted(cached, key=lambda x: x[0].filemode)
        return render_template("objects/tree.html",
                  repo = self.repo,
                  revspec = self.revspec, rev = rev, files = files,
                  path = self.path)

    def _render_tag(self, rev):
        obj = self.repo[rev.target]
        url = url_for('obj', reponame=self.repo.get_name(), revspec = obj.hex)
        return redirect(url)

    def render_obj(self):
        rev = self.repo.revparse_single(self.revspec)
        return self.object_map[type(rev)](rev)
Example #29
0
def git_is_clean(srcdir, project):
    repo = Repository(os.path.join(srcdir, project.workspace_path, ".git"))
    for _, b in iteritems(repo.status()):
        if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT:
            return False, "has uncommitted changes"
    if repo.head_is_detached:
        return False, "has detached HEAD"
    origin = get_origin(repo, project)
    if not origin:
        return False, "has no upstream remote"
    remote_refs = []
    local_refs = {}
    for refname in repo.listall_references():
        if refname.startswith("refs/remotes/%s/" % origin.name):
            ref = repo.lookup_reference(refname)
            if ref.type == GIT_REF_OID:
                remote_refs.append(ref.target)
        elif not refname.startswith("refs/remotes/"):
            ref = repo.lookup_reference(refname)
            if ref.type == GIT_REF_OID:
                local_refs[ref.peel().id] = refname
    if not remote_refs:
        return False, "has no upstream remote branches"
    if not local_refs:
        return False, "has no local branches"
    if not repo.lookup_branch("%s/%s" % (origin.name, project.master_branch), GIT_BRANCH_REMOTE):
        return False, "has no upstream master branch"
    for remote_ref in remote_refs:
        for commit in repo.walk(remote_ref):
            if commit.id in local_refs:
                del local_refs[commit.id]
    if local_refs:
        return False, "has local commits: %s" % ", ".join(["'%s'" % name for _, name in iteritems(local_refs)])
    return True, ""
def cross_reference_commits_with_bug_reports():
    repos_root = sys.argv[1]#"/home/kevin/Desktop/eclipse-platform"#
    bug_reports_file = sys.argv[2]#"/home/kevin/Downloads/eclipse-bugs.csv"#

    with open(bug_reports_file, newline="") as csv_file:
        bug_reports = [{"id": bug["id"],
                        "creation_time": datetime.strptime(bug["creation_time"], bug_date_format),
                        "closed_time": datetime.strptime(bug["closed_time"], bug_date_format)}
                       for bug in csv.DictReader(csv_file)]

    os.makedirs(output_root_path)

    for git_repo in get_immediate_subdirectories(repos_root):
        repo_name = os.path.basename(os.path.normpath(git_repo))
        repo = Repository(os.path.join(git_repo, git_folder))
        bug_related_commits = [commit for commit in repo.walk(repo.head.target) if is_bug_related(commit)]

        root = etree.Element("commits")
        count = 0

        for bug_report in bug_reports:

            # This may actually hurt the detection
            bug_related_commits_within_bug_life = \
                [c for c in bug_related_commits
                 if bug_report['creation_time'] <= datetime.fromtimestamp(c.commit_time) <= bug_report['closed_time']]

            # for commit in bug_related_commits:
            for commit in bug_related_commits_within_bug_life:
                if are_related(commit, bug_report):
                    commit_xml = commit_to_xml(commit)
                    commit_xml.set("related_bug", bug_report["id"])
                    root.append(commit_xml)
                    count += 1

            print("repo: " + repo_name + ", bug: " + bug_report["id"] + " processed")

            # if count > 10:
            #     break

        root.set("count", str(count))
        output_xml = xml_to_string(root)

        with open(os.path.join(output_root_path, repo_name + "_" + output_commit_file), "w") as file:
            file.write(output_xml)
Example #31
0
class ChangeCtxDefault(ChangeCtx):
    """Class with the specific implementation details for the change context
    of the default revision state of the repository. It inherits the common
    implementation from the class :class:`ChangeCtxBase`.
    """

    def __init__(self, repo_path):
        self._repo_path = repo_path
        self._repo = Repository(self._repo_path)
        self._ctx = self._repo[self.revision_id]

    @locked_cached_property
    def files(self):
        def r(_files, repo, tree, prefix=None):
            for entry in tree:
                obj = repo[entry.oid]
                filename = prefix and (prefix + '/' + entry.name) or entry.name
                if obj.type == GIT_OBJ_TREE:
                    r(_files, repo, obj, filename)
                elif obj.type == GIT_OBJ_BLOB:
                    _files.append(filename)
                else:
                    raise RuntimeError('Invalid object: %s' % filename)
        f = []
        r(f, self._repo, self._ctx.tree)
        return sorted(f)

    @locked_cached_property
    def revision_id(self):
        """This property should be cached because the lookup_reference method
        reloads itself.
        """
        try:
            ref = self._repo.lookup_reference('refs/heads/master')
        except Exception:
            raise RuntimeError('Branch "master" not found!')
        return ref.target

    def needs_reload(self):
        try:
            ref = self._repo.lookup_reference('refs/heads/master')
        except Exception:
            return True
        return self.revision_id != ref.target

    def filectx_needs_reload(self, filectx):
        try:
            ref = self._repo.lookup_reference('refs/heads/master')
        except Exception:
            raise RuntimeError('Branch "master" not found!')
        return filectx._changectx.oid != ref.target

    def published(self, date, now):
        return date <= now

    def etag(self, filectx):
        return 'blohg-%i-%i-%s' % (filectx.mdate or filectx.date,
                                   len(filectx.data),
                                   adler32(filectx.path.encode('utf-8'))
                                   & 0xffffffff)

    def get_filectx(self, path):
        return FileCtx(self._repo, self._ctx, path)
Example #32
0
# Read the configuration file with parameters,
# location of configuration file - as in production system
asa_parameters = configread(conf_file, 'CiscoASA', 'enablepw')

git_parameters = configread(conf_file, 'GIT', 'author_name', 'committer_name',
                            'author_email', 'committer_email')

nd_parameters = configread(conf_file, 'NetworkDevice', 'login', 'password',
                           'slack_hook', 'device_file', 'savedir')

if not os.path.isdir(nd_parameters['savedir']):
    os.makedirs(nd_parameters['savedir'])

# Try to create object repository if repository is already exist
try:
    repo = Repository(nd_parameters['savedir'])
except KeyError:
    repo = init_repository(nd_parameters['savedir'])
    git_init = True

# Build the index of repository
index = repo.index

device_list_file = open(nd_parameters['device_file'])

# Parse the device file
for device_line in device_list_file:
    device_params = device_line.split(':')
    device_type = device_params[0]
    device_name = device_params[1]
    device_ip = device_params[2]
Example #33
0
class GitBareBackend(object):

    nb_transactions = 0

    def __init__(self, path):
        self.path = abspath(path) + '/'
        # Open database
        self.path_data = '%s/database/' % self.path
        if not lfs.is_folder(self.path_data):
            error = '"%s" should be a folder, but it is not' % path
            raise ValueError, error
        # Open repository
        self.repo = Repository(self.path_data)
        # Read index
        try:
            tree = self.repo.head.peel(GIT_OBJ_TREE)
            self.repo.index.read_tree(tree.id)
        except:
            pass
        # Check git commiter
        try:
            _, _ = self.username, self.useremail
        except:
            print '========================================='
            print 'ERROR: Please configure GIT commiter via'
            print ' $ git config --global user.name'
            print ' $ git config --global user.email'
            print '========================================='
            raise

    @classmethod
    def init_backend(cls, path, init=False, soft=False):
        init_repository('{0}/database'.format(path), bare=True)

    #######################################################################
    # Internal utility functions
    #######################################################################
    def _call(self, command):
        """Interface to cal git.git for functions not yet implemented using
        libgit2.
        """
        popen = Popen(command, stdout=PIPE, stderr=PIPE, cwd=self.path_data)
        stdoutdata, stderrdata = popen.communicate()
        if popen.returncode != 0:
            raise EnvironmentError, (popen.returncode, stderrdata)
        return stdoutdata

    @lazy
    def username(self):
        cmd = ['git', 'config', '--get', 'user.name']
        try:
            username = self._call(cmd).rstrip()
        except EnvironmentError:
            raise ValueError(
                "Please configure 'git config --global user.name'")
        return username

    @lazy
    def useremail(self):
        cmd = ['git', 'config', '--get', 'user.email']
        try:
            useremail = self._call(cmd).rstrip()
        except EnvironmentError:
            raise ValueError(
                "Please configure 'git config --global user.email'")
        return useremail

    def _resolve_reference(self, reference):
        """This method returns the SHA the given reference points to. For now
        only HEAD is supported.

        FIXME This is quick & dirty. TODO Implement references in pygit2 and
        use them here.
        """
        # Case 1: SHA
        if len(reference) == 40:
            return reference

        # Case 2: reference
        reference = self.repo.lookup_reference(reference)
        try:
            reference = reference.resolve()
        except KeyError:
            return None

        return reference.target

    def normalize_key(self, path, __root=None):
        # Performance is critical so assume the path is already relative to
        # the repository.
        key = __root.resolve(path)
        if key and key[0] == '.git':
            err = "bad '{0}' path, access to the '.git' folder is denied"
            raise ValueError(err.format(path))
        return '/'.join(key)

    def handler_exists(self, key):
        tree = self.repo.head.peel(GIT_OBJ_TREE)
        try:
            tree[key]
        except:
            return False
        return True

    def get_handler_names(self, key):
        try:
            tree = self.repo.head.peel(GIT_OBJ_TREE)
            if key:
                tree_entry = tree[key]
                if tree_entry.type == 'blob':
                    raise ValueError
                tree = self.repo[tree_entry.id]
        except:
            yield None
        else:
            for item in tree:
                yield item.name

    def get_handler_data(self, key):
        tree = self.repo.head.peel(GIT_OBJ_TREE)
        tree_entry = tree[key]
        blob = self.repo[tree_entry.id]
        return blob.data

    def get_handler_mimetype(self, key):
        data = self.get_handler_data(key)
        return magic_from_buffer(data)

    def handler_is_file(self, key):
        return not self.handler_is_folder(key)

    def handler_is_folder(self, key):
        repository = self.repo
        if key == '':
            return True
        else:
            tree = repository.head.peel(GIT_OBJ_TREE)
            tree_entry = tree[key]
        return tree_entry.type == 'tree'

    def get_handler_mtime(self, key):
        # FIXME
        return datetime.utcnow().replace(tzinfo=fixed_offset(0))

    def traverse_resources(self):
        tree = self.repo.head.peel(GIT_OBJ_TREE)
        yield self.get_resource('/')
        for name in self.get_names(tree):
            if name[-9:] == '.metadata' and name != '.metadata':
                yield self.get_resource('/' + name[:-9])

    def get_names(self, tree, path=''):
        for entry in tree:
            base_path = '{0}/{1}'.format(path, entry.name)
            yield base_path
            if entry.filemode == GIT_FILEMODE_TREE:
                sub_tree = self.repo.get(entry.hex)
                for x in self.get_names(sub_tree, base_path):
                    yield x

    def do_transaction(self, commit_message, data, added, changed, removed,
                       handlers):
        self.nb_transactions += 1
        # Get informations
        git_author, git_date, git_msg, docs_to_index, docs_to_unindex = data
        git_msg = commit_message or git_msg or 'no comment'
        # List of Changed
        added_and_changed = list(added) + list(changed)
        # Build the tree from index
        index = self.repo.index
        for key in added_and_changed:
            handler = handlers.get(key)
            blob_id = self.repo.create_blob(handler.to_str())
            entry = IndexEntry(key, blob_id, GIT_FILEMODE_BLOB_EXECUTABLE)
            index.add(entry)
        for key in removed:
            index.remove(key)
        git_tree = index.write_tree()
        # Commit
        self.git_commit(git_msg, git_author, git_date, tree=git_tree)

    def git_commit(self, message, author=None, date=None, tree=None):
        """Equivalent to 'git commit', we must give the message and we can
        also give the author and date.
        """
        # Tree
        if tree is None:
            #tree = self.index.write_tree()
            raise ValueError('Please give me a tree')

        # Parent
        parent = self._resolve_reference('HEAD')
        parents = [parent] if parent else []

        # Committer
        when_time = time.time()
        when_offset = -(time.altzone if time.daylight else time.timezone)
        when_offset = when_offset / 60

        name = self.username
        email = self.useremail
        committer = Signature(name, email, when_time, when_offset)

        # Author
        if author is None:
            author = (name, email)

        if date:
            if date.tzinfo:
                from pytz import utc
                when_time = date.astimezone(utc)  # To UTC
                when_time = when_time.timetuple()  # As struct_time
                when_time = timegm(when_time)  # To unix time
                when_offset = date.utcoffset().seconds / 60
            else:
                err = "Worktree.git_commit doesn't support naive datatime yet"
                raise NotImplementedError, err

        author = Signature(author[0], author[1], when_time, when_offset)

        # Create the commit
        return self.repo.create_commit('HEAD', author, committer, message,
                                       tree, parents)

    def abort_transaction(self):
        # TODO: Remove created blobs
        pass
Example #34
0
class GitRepo:
    """A class that manages a git repository.

    This class enables versiong via git for a repository.
    You can stage and commit files and checkout different commits of the repository.
    """

    path = ''
    pathspec = []
    repo = None
    callback = None
    author_name = 'QuitStore'
    author_email = '*****@*****.**'
    gcProcess = None

    def __init__(self, path, origin=None, gc=False):
        """Initialize a new repository from an existing directory.

        Args:
            path: A string containing the path to the repository.
            origin: The remote URL where to clone and fetch from and push to
        """
        logger = logging.getLogger('quit.core.GitRepo')
        logger.debug('GitRepo, init, Create an instance of GitStore')
        self.path = path
        self.gc = gc

        if not exists(path):
            try:
                makedirs(path)
            except OSError as e:
                raise Exception('Can\'t create path in filesystem:', path, e)

        try:
            self.repo = Repository(path)
        except KeyError:
            pass
        except AttributeError:
            pass

        if origin:
            self.callback = QuitRemoteCallbacks()

        if self.repo:
            if self.repo.is_bare:
                raise QuitGitRepoError('Bare repositories not supported, yet')

            if origin:
                # set remote
                self.addRemote('origin', origin)
        else:
            if origin:
                # clone
                self.repo = self.cloneRepository(origin, path, self.callback)
            else:
                self.repo = init_repository(path=path, bare=False)

    def cloneRepository(self, origin, path, callback):
        try:
            repo = clone_repository(url=origin,
                                    path=path,
                                    bare=False,
                                    callbacks=callback)
            return repo
        except Exception as e:
            raise QuitGitRepoError(
                "Could not clone from: {} origin. {}".format(origin, e))

    def addall(self):
        """Add all (newly created|changed) files to index."""
        self.repo.index.read()
        self.repo.index.add_all(self.pathspec)
        self.repo.index.write()

    def addfile(self, filename):
        """Add a file to the index.

        Args:
            filename: A string containing the path to the file.
        """
        index = self.repo.index
        index.read()

        try:
            index.add(filename)
            index.write()
        except Exception as e:
            logger.info(
                "GitRepo, addfile, Could not add file  {}.".format(filename))
            logger.debug(e)

    def addRemote(self, name, url):
        """Add a remote.

        Args:
            name: A string containing the name of the remote.
            url: A string containing the url to the remote.
        """
        try:
            self.repo.remotes.create(name, url)
            logger.info("Successfully added remote: {} - {}".format(name, url))
        except Exception as e:
            logger.info("Could not add remote: {} - {}".format(name, url))
            logger.debug(e)

        try:
            self.repo.remotes.set_push_url(name, url)
            self.repo.remotes.set_url(name, url)
        except Exception as e:
            logger.info("Could not set push/fetch urls: {} - {}".format(
                name, url))
            logger.debug(e)

    def checkout(self, commitid):
        """Checkout a commit by a commit id.

        Args:
            commitid: A string cotaining a commitid.
        """
        try:
            commit = self.repo.revparse_single(commitid)
            self.repo.set_head(commit.oid)
            self.repo.reset(commit.oid, GIT_RESET_HARD)
            logger.info("Checked out commit: {}".format(commitid))
        except Exception as e:
            logger.info("Could not check out commit: {}".format(commitid))
            logger.debug(e)

    def commit(self, message=None):
        """Commit staged files.

        Args:
            message: A string for the commit message.
        Raises:
            Exception: If no files in staging area.
        """
        if self.isstagingareaclean():
            # nothing to commit
            return

        index = self.repo.index
        index.read()
        tree = index.write_tree()

        try:
            author = Signature(self.author_name, self.author_email)
            comitter = Signature(self.author_name, self.author_email)

            if len(self.repo.listall_reference_objects()) == 0:
                # Initial Commit
                if message is None:
                    message = 'Initial Commit from QuitStore'
                self.repo.create_commit('HEAD', author, comitter, message,
                                        tree, [])
            else:
                if message is None:
                    message = 'New Commit from QuitStore'
                self.repo.create_commit('HEAD', author, comitter, message,
                                        tree,
                                        [self.repo.head.get_object().hex])
            logger.info('Updates commited')
        except Exception as e:
            logger.info('Nothing to commit')
            logger.debug(e)

        if self.gc:
            self.garbagecollection()

    def commitexists(self, commitid):
        """Check if a commit id is part of the repository history.

        Args:
            commitid: String of a Git commit id.
        Returns:
            True, if commitid is part of commit log
            False, else.
        """
        if commitid in self.getids():
            return True
        else:
            return False

    def garbagecollection(self):
        """Start garbage collection.

        Args:
            commitid: A string cotaining a commitid.
        """
        try:
            # Check if the garbage collection process is still running
            if self.gcProcess is None or self.gcProcess.poll() is not None:
                # Start garbage collection with "--auto" option,
                # which imidietly terminates, if it is not necessary
                self.gcProcess = Popen(["git", "gc", "--auto", "--quiet"],
                                       cwd=self.path)
                logger.debug('Spawn garbage collection')
        except Exception as e:
            logger.debug('Git garbage collection failed to spawn')
            logger.debug(e)

    def getpath(self):
        """Return the path of the git repository.

        Returns:
            A string containing the path to the directory of git repo
        """
        return self.path

    def getcommits(self):
        """Return meta data about exitsting commits.

        Returns:
            A list containing dictionaries with commit meta data
        """
        commits = []
        if len(self.repo.listall_reference_objects()) > 0:
            for commit in self.repo.walk(self.repo.head.target,
                                         GIT_SORT_REVERSE):
                commits.append({
                    'id':
                    str(commit.oid),
                    'message':
                    str(commit.message),
                    'commit_date':
                    datetime.fromtimestamp(
                        commit.commit_time).strftime('%Y-%m-%dT%H:%M:%SZ'),
                    'author_name':
                    commit.author.name,
                    'author_email':
                    commit.author.email,
                    'parents': [c.hex for c in commit.parents],
                })
        return commits

    def getids(self):
        """Return meta data about exitsting commits.

        Returns:
            A list containing dictionaries with commit meta data
        """
        ids = []
        if len(self.repo.listall_reference_objects()) > 0:
            for commit in self.repo.walk(self.repo.head.target,
                                         GIT_SORT_REVERSE):
                ids.append(str(commit.oid))
        return ids

    def isgarbagecollectionon(self):
        """Return if gc is activated or not.

        Returns:
            True, if activated
            False, if not
        """
        return self.gc

    def isstagingareaclean(self):
        """Check if staging area is clean.

        Returns:
            True, if staginarea is clean
            False, else.
        """
        status = self.repo.status()

        for filepath, flags in status.items():
            if flags != GIT_STATUS_CURRENT:
                return False

        return True

    def pull(self, remote='origin', branch='master'):
        """Pull if possible.

        Return:
            True: If successful.
            False: If merge not possible or no updates from remote.
        """
        try:
            self.repo.remotes[remote].fetch()
        except Exception as e:
            logger.info("Can not pull:  Remote {} not found.".format(remote))
            logger.debug(e)

        ref = 'refs/remotes/' + remote + '/' + branch
        remoteid = self.repo.lookup_reference(ref).target
        analysis, _ = self.repo.merge_analysis(remoteid)

        if analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE:
            # Already up-to-date
            pass
        elif analysis & GIT_MERGE_ANALYSIS_FASTFORWARD:
            # fastforward
            self.repo.checkout_tree(self.repo.get(remoteid))
            master_ref = self.repo.lookup_reference('refs/heads/master')
            master_ref.set_target(remoteid)
            self.repo.head.set_target(remoteid)
        elif analysis & GIT_MERGE_ANALYSIS_NORMAL:
            self.repo.merge(remoteid)
            tree = self.repo.index.write_tree()
            msg = 'Merge from ' + remote + ' ' + branch
            author = Signature(self.author_name, self.author_email)
            comitter = Signature(self.author_name, self.author_email)
            self.repo.create_commit('HEAD', author, comitter, msg, tree,
                                    [self.repo.head.target, remoteid])
            self.repo.state_cleanup()
        else:
            logger.debug('Can not pull. Unknown merge analysis result')

    def push(self, remote='origin', branch='master'):
        """Push if possible.

        Return:
            True: If successful.
            False: If diverged or nothing to push.
        """
        ref = ['refs/heads/' + branch]

        try:
            remo = self.repo.remotes[remote]
        except Exception as e:
            logger.info(
                "Can not push. Remote: {} does not exist.".format(remote))
            logger.debug(e)
            return

        try:
            remo.push(ref, callbacks=self.callback)
        except Exception as e:
            logger.info("Can not push to {} with ref {}".format(
                remote, str(ref)))
            logger.debug(e)

    def getRemotes(self):
        remotes = {}

        try:
            for remote in self.repo.remotes:
                remotes[remote.name] = [remote.url, remote.push_url]
        except Exception as e:
            logger.info('No remotes found.')
            logger.debug(e)
            return {}

        return remotes
Example #35
0
parser = argparse.ArgumentParser(
    description='Run Kiln for every commit on a master branch in a git repo')
parser.add_argument('dir')
parser.add_argument('app_name')
parser.add_argument('data_collector_url')
args = parser.parse_args()
proj_dir = vars(args)['dir']
app_name = vars(args)['app_name']
url = vars(args)['data_collector_url']

repo_path = discover_repository(proj_dir)
if repo_path == None:
    raise Exception("Project directory isn't a git repo. Exiting!")

repo = Repository(repo_path)
walker = repo.walk(repo.branches['master'].peel().id,
                   GIT_SORT_REVERSE | GIT_SORT_TIME)
walker.simplify_first_parent()
all_commits = [x.id for x in walker]
kiln_config_path = os.path.abspath(os.path.join(proj_dir, "kiln.toml"))
for commit in all_commits:
    if commit == "":
        continue
    subprocess.check_call(["git", "reset", "--hard", "HEAD"],
                          cwd=proj_dir,
                          stdout=subprocess.DEVNULL,
                          stderr=subprocess.DEVNULL)
    subprocess.check_call(["git", "checkout", str(commit)],
                          cwd=proj_dir,
                          stdout=subprocess.DEVNULL,
Example #36
0
import pytest

logging.info('Checking if test-metric recording needs to be enabled')
if 'TEST_METRICS_URL' in os.environ:
    import datetime
    import getpass
    import json
    import socket
    from timeit import default_timer as timer

    from pygit2 import Repository

    from tests.cook import util

    repository_path = os.path.abspath(f'{os.path.dirname(os.path.abspath(__file__))}/../..')
    repo = Repository(repository_path)
    head = repo.head
    commit = repo.revparse_single('HEAD')
    git_branch = head.name.replace('refs/heads/', '')
    git_commit_hex = commit.hex
    elastic_search_url = os.getenv('TEST_METRICS_URL').rstrip('/')
    logging.info(f'Sending test metrics to {elastic_search_url}')


    @pytest.fixture()
    def record_test_metric(request):
        start = timer()
        yield
        try:
            end = timer()
            now = datetime.datetime.utcnow()
def parse_code_churns(pid, repo_path, branch, start, stop=-1):
    """
    Function that is intended to be runned by a process. It extracts the code churns
    for a set of commits and stores them in the RES dict.
    """
    repo = Repository(repo_path)

    head = repo.references.get(branch)
    commits = list(
        repo.walk(head.target, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE))

    start = start - 1 if (start > 0) else start
    commits = commits[start:stop] if (stop != -1) else commits[start:]

    code_churns = [[] for c in range(len(commits))]
    for i, commit in enumerate(tqdm(commits[1:], position=pid)):
        diff = repo.diff(commits[i], commit)

        tree = commit.tree
        patches = [p for p in diff]
        stats = diff.stats

        # Count the total lines of code and find the biggest file that have been changed
        total_tloc = 0
        line_of_code_old = 0
        for patch in patches:
            if patch.delta.is_binary:
                continue
            new_file = patch.delta.new_file

            # Total lines of code
            total_tloc += get_file_lines_of_code(repo, tree, new_file)

            old_file = patch.delta.old_file
            # Total lines of code in the old file
            line_of_code_old = max(
                line_of_code_old, get_file_lines_of_code(repo, tree, old_file))

        # Churned lines of code
        cloc = stats.insertions
        # Deleted lines of code
        dloc = stats.deletions

        # Churned files
        files_churned = len(patches)

        # File count
        num_files = count_files(tree, repo)

        # Apply relative code churns
        measure_one = float(cloc) / total_tloc if (
            total_tloc > 0) else float(cloc)
        measure_two = float(dloc) / total_tloc if (
            total_tloc > 0) else float(cloc)
        measure_three = (float(files_churned) / num_files if
                         (num_files > 0) else float(files_churned))

        line_of_code_old = float(line_of_code_old)

        # Churn features
        code_churns[i].append(str(commit.hex))
        code_churns[i].append(str(measure_one))
        code_churns[i].append(str(measure_two))
        code_churns[i].append(str(measure_three))
        code_churns[i].append(str(line_of_code_old))

    RES[pid] = code_churns
Example #38
0
 def do_put(content_path, object_hashes, content, filename):
     """Perform put operation. This is used in the distributed wrapper"""
     content_hash = Repository(content_path).create_blob(content)
     result = object_hashes[filename] = str(content_hash)
     return result
Example #39
0
class PyGitEngine(GitContentDatabaseEngine):
    def __init__(self, config):
        super(PyGitEngine, self).__init__(config)
        self.repo = None

    def connect(self):
        """Create content directory"""
        if not isdir(self.content_path):
            init_repository(self.content_path, bare=True)
            self.repo = Repository(self.content_path)
            self.create_initial_commit()
        else:
            self.repo = Repository(self.content_path)

    @staticmethod
    def do_put(content_path, object_hashes, content, filename):
        """Perform put operation. This is used in the distributed wrapper"""
        content_hash = Repository(content_path).create_blob(content)
        result = object_hashes[filename] = str(content_hash)
        return result

    def put_attr(self, content, filename):
        """Return attributes for the do_put operation"""
        filename = self._inc_name(filename)
        return (self.content_path, self.object_hashes, content, filename)

    def put(self, content, filename="generic"):  # pylint: disable=method-hidden
        """Put content in the content database"""
        return self.do_put(*self.put_attr(content, filename))

    def get(self, content_hash):  # pylint: disable=method-hidden
        """Get content from the content database"""
        return_data = self.repo[content_hash].data
        return return_data

    def find_subhash(self, content_hash):
        """Find hash in git"""
        try:
            blob = self.repo.revparse_single(content_hash)
            return str(blob.id)
        except KeyError:
            return None

    def create_initial_commit(self):
        """Create the initial commit of the git repository"""
        empty_tree = self.repo.TreeBuilder().write()
        self.create_commit_object(self._initial_message, empty_tree)

    def create_commit_object(self, message, tree):
        """Create a commit object"""
        references = list(self.repo.references)

        master_ref = self.repo.lookup_reference(
            self._commit_ref) if len(references) > 0 else None

        parents = []
        if master_ref is not None:
            parents = [master_ref.peel().id]

        author = Signature(self._commit_name, self._commit_email)
        return self.repo.create_commit(self._commit_ref, author, author,
                                       message, tree, parents)

    def new_tree(self, parent):
        """Create new git tree"""
        return self.repo.TreeBuilder()

    def insert_blob(self, tree, basename, value):
        """Insert blob into tree"""
        tree.insert(basename, value, GIT_FILEMODE_BLOB)

    def insert_tree(self, tree, basename, value):
        """Insert tree into tree"""
        tree.insert(basename, value, GIT_FILEMODE_TREE)

    def write_tree(self, tree):
        """Write tree to git directory"""
        return tree.write()
Example #40
0
                        default=False, help="Stage and commit all dirty state")
parser.add_argument("--push", dest="wip_push", action="store_true",
                        default=False, help="Push WIP to default upstream")
parser.add_argument("--force", dest="wip_force", action="store_true",
                        default=False, help="Force saving WIP (ignore idle time)")
parser.add_argument("--branch-ref", dest="wip_add_branch_name", action="store_true",
                        default=False, help="Prepend WIP commit message with current branch name")


args = parser.parse_args()

if not is_repo(os.getcwd()):
    log_error("Not a git repo")
    sys.exit(1)

repo = Repository(os.getcwd() + "/.git")
config = repo.config

remote_url = repo.remotes[args.remote].url
pass_path = None
for glob in credentials_mapping.keys():
    if fnmatch.fnmatch(remote_url, glob):
        pass_path = credentials_mapping[glob]["target"]


if not args.wip_force and not is_idle_enough("xprintidle-ng"):
    sys.exit(0)
diff_size = get_diff_size(repo)
if diff_size == 0:
    log_info("no changes to commit")
    sys.exit(0)
Example #41
0
    parser.add_argument("-r", "--git-repo", help="Git repo base directory")
    parser.add_argument("-s", "--start-date", help="YYYY-MM-DD format, default to 2016-07-01")
    parser.add_argument("-e", "--end-date", help="YYYY-MM-DD format, default to 2016-10-01")
    parser.add_argument("-j", "--jira-issues", help="CSV file containing JIRA tickets to correlate commits with (optional)")

    args = parser.parse_args()
    if not args.git_repo:
        raise ValueError("git-repo mandatory")
    if not args.start_date:
        args.start_date = "2016-07-01"
    if not args.end_date:
        args.end_date = "2016-10-01"
    return args

args = parse_args()
repo = Repository(args.git_repo)
startDate = datetime.strptime(args.start_date, "%Y-%m-%d")
endDate = datetime.strptime(args.end_date, "%Y-%m-%d")
jiraIssuesCsvFilename = args.jira_issues

print "Analyzing repo", repo, "for commits between", startDate, "and", endDate
commits = [commit for commit in repo.walk(repo[repo.head.target].id, GIT_SORT_TOPOLOGICAL | GIT_SORT_TIME | GIT_SORT_REVERSE)]
print "Initial nb of commits: ", len(commits)
commits = filter(GitCommitDateRangeFilter(startDate, endDate).filter, commits)
print "Commits matching date range: ", len(commits)
if jiraIssuesCsvFilename:
    jiraKeysExtractor = CsvJiraKeysExtractor(jiraIssuesCsvFilename)
    commits = filter(GitCommitJiraFilter(jiraKeysExtractor.extract()).filter, commits)
    print "Commits matching JIRA tickets: ", len(commits)
else:
    print "No filtering based on JIRA tickets"
Example #42
0
def getcurrentrepo():
    try:
        return Repository(r'.').head.shorthand
    except:
        return ""
Example #43
0
def update_projects(srcdir,
                    packages,
                    projects,
                    other_git,
                    ws_state,
                    config,
                    update_op,
                    jobs,
                    dry_run=False,
                    action="update",
                    fetch_remote=True):
    if (pygit2_features & GIT_FEATURE_HTTPS) == 0:
        warning("your libgit2 has no built-in HTTPS support\n")
    if (pygit2_features & GIT_FEATURE_SSH) == 0:
        warning("your libgit2 has no built-in SSH support\n")
    git_remote_callback = GitRemoteCallback(config)
    manager = create_multiprocess_manager()
    L = manager.Lock()
    d = manager.dict()
    workload = [(project, project.workspace_path)
                for project in projects] + [(None, path) for path in other_git]
    result = run_multiprocess_workers(partial(fetch_worker, srcdir,
                                              git_remote_callback,
                                              fetch_remote, dry_run),
                                      workload,
                                      worker_init=fetch_worker_init,
                                      worker_init_args=(L, d),
                                      jobs=jobs,
                                      timeout=900)
    done = 0
    errors = 0
    for r in result:
        project, path, e = r
        try:
            if not e:
                repo = Repository(os.path.join(srcdir, path, ".git"))
                head_branch, master_branch, tracking_branch = lookup_branches(
                    repo, project)
                if update_op(repo, path, head_branch, master_branch,
                             tracking_branch):
                    done += 1
            else:
                error("cannot fetch remotes for '%s': %s\n" %
                      (escape(path), escape(str(e))))
                errors += 1
        except Exception as e:
            error("cannot %s '%s': %s\n" %
                  (action, escape(path), escape(str(e))))
            errors += 1
    if done:
        report = ("%s completed successfully for" %
                  action.title()) if not dry_run else (
                      "Dry-run: %s would have been executed for" % action)
        if done == 1:
            msg("@!%s one repository@|\n" % report)
        else:
            msg("@!%s %d repositories@|\n" % (report, done))
    if errors:
        if errors == 1:
            warning("an error has occurred\n")
        else:
            warning("%d errors have occurred\n" % errors)
Example #44
0
 def __init__(self, repo_path):
     self._repo_path = repo_path
     self._repo = Repository(self._repo_path)
     self._ctx = self._repo[self.revision_id]
def get_code_churns(repo_path, branch):
    """
    General function for extracting code churns. It first extracts the code churns for
    the first commit and then starts a number of processes(equal to the number of cores
    on the computer), which equally extracts the code churns for the remaining commits.
    """
    repo = Repository(repo_path)

    print(repo)
    print(repo.references)
    head = repo.references.get(branch)

    commits = list(
        repo.walk(head.target, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE))
    code_churns = [[]]

    initial = commits[0]

    # Relative code churns
    measure_one = 0.0
    measure_two = 0.0
    measure_three = 1.0

    line_of_code_old = 0.0

    code_churns[0].append(str(initial.hex))
    code_churns[0].append(str(measure_one))
    code_churns[0].append(str(measure_two))
    code_churns[0].append(str(measure_three))
    code_churns[0].append(str(line_of_code_old))

    # Check how many processes that could be spawned
    cpus = cpu_count()
    print("Using {} cpus...".format(cpus))

    # Equally split the commit set into the equally sized parts.
    quote, remainder = divmod(len(commits), cpus)

    processes = [
        Process(target=parse_code_churns,
                args=(i, repo_path, branch, i * quote + min(i, remainder),
                      (i + 1) * quote + min(i + 1, remainder)))
        for i in range(cpus)
    ]

    for process in processes:
        process.start()

    start_time = time.time()
    for process in processes:
        process.join()
    end_time = time.time()

    print("Done")
    print("Overall processing time {}".format(end_time - start_time))

    # Assemble the results
    churns = []
    for _, churn in RES.items():
        churns.extend(churn)

    churns = list(reversed(churns))
    churns.append(code_churns[0])
    return churns
Example #46
0
def get_head_branch(working_dir):
    repo = Repository(working_dir + '.git')
    return repo.head.name
Example #47
0
def git_repo(cwd):
    repo_path = pygit2.discover_repository(cwd)
    if repo_path is None:
        return

    return Repository(repo_path)
Example #48
0
def lambda_handler(event, context):
    keybucket = event['context']['key-bucket']
    outputbucket = event['context']['output-bucket']
    pubkey = event['context']['public-key']
    ### Source IP ranges to allow requests from, if the IP is in one of these the request will not be chacked for an api key
    ipranges = []
    for i in event['context']['allowed-ips'].split(','):
        ipranges.append(ip_network(u'%s' % i))
    ### APIKeys, it is recommended to use a different API key for each repo that uses this function
    apikeys = event['context']['api-secrets'].split(',')
    ip = ip_address(event['context']['source-ip'])
    secure = False
    for net in ipranges:
        if ip in net:
            secure = True
    if 'X-Gitlab-Token' in event['params']['header'].keys():
        if event['params']['header']['X-Gitlab-Token'] in apikeys:
            secure = True
    if 'X-Git-Token' in event['params']['header'].keys():
        if event['params']['header']['X-Git-Token'] in apikeys:
            secure = True
    if 'X-Gitlab-Token' in event['params']['header'].keys():
        if event['params']['header']['X-Gitlab-Token'] in apikeys:
            secure = True
    if 'X-Hub-Signature' in event['params']['header'].keys():
        for k in apikeys:
            if hmac.new(
                    str(k), str(event['context']['raw-body']),
                    hashlib.sha1).hexdigest() == str(
                        event['params']['header']['X-Hub-Signature'].replace(
                            'sha1=', '')):
                secure = True
    if not secure:
        logger.error('Source IP %s is not allowed' %
                     event['context']['source-ip'])
        raise Exception('Source IP %s is not allowed' %
                        event['context']['source-ip'])
    try:
        repo_name = event['body-json']['project']['path_with_namespace']
    except:
        repo_name = event['body-json']['repository']['full_name']
    try:
        remote_url = event['body-json']['project']['git_ssh_url']
    except:
        try:
            remote_url = 'git@' + event['body-json']['repository'][
                'links']['html']['href'].replace('https://', '').replace(
                    '/', ':', 1) + '.git'
        except:
            remote_url = event['body-json']['repository']['ssh_url']
    repo_path = '/tmp/%s' % repo_name
    creds = RemoteCallbacks(credentials=get_keys(keybucket, pubkey), )
    try:
        repository_path = discover_repository(repo_path)
        repo = Repository(repository_path)
        logger.info('found existing repo, using that...')
    except:
        logger.info('creating new repo for %s in %s' % (remote_url, repo_path))
        repo = create_repo(repo_path, remote_url, creds)
    pull_repo(repo, remote_url, creds)
    zipfile = zip_repo(repo_path, repo_name)
    push_s3(zipfile, repo_name, outputbucket)
    if cleanup:
        logger.info('Cleanup Lambda container...')
        shutil.rmtree(repo_path)
        shutil.rm(zipfile)
        shutil.rm('/tmp/id_rsa')
        shutil.rm('/tmp/id_rsa.pub')
    return 'Successfully updated %s' % repo_name
Example #49
0
def repository(path):
    try:
        repo = Repository(path)
    except KeyError:
        raise JagareError('repo %s not exists' % path)
    return repo
class Project1Test(unittest.TestCase):
    def __init__(self, test_name, grader):
        super(Project1Test, self).__init__(test_name)
        self.grader = grader

    # setUpClass doesn't work!?
    def setUp(self):
        self.out_string = ""
        self.repo = REPO_TEMPLATE % self.grader.andrewid
        os.chdir(self.grader.tmp_dir)
        try:
            self.tearDown()
        except:
            pass
        self.git_clone(self.grader.root_repo)
        os.chdir(self.repo)
        self.repository = Repository('.git')
        commit = self.resolve_tag()
        self.git_checkout(commit.hex)
        self.ran = False
        self.port = random.randint(1025, 9999)
        self.tls_port = random.randint(1025, 9999)
        print '\nUsing ports: %d,%d' % (self.port, self.tls_port)

    def pAssertEqual(self, arg1, arg2):
        try:
            self.assertEqual(arg1, arg2)
        except Exception as e:
            self.print_str(traceback.format_stack()[-2])
            raise e

    def pAssertTrue(self, test):
        try:
            self.assertTrue(test)
        except Exception as e:
            self.print_str(traceback.format_stack()[-2])
            raise e

    def print_str(self, prt_str):
        print(prt_str)
        self.out_string += ("\n" + prt_str)

    def edit_notes(self, new_note):
        notef = self.grader.notes
        try:
            check_both('cat %s' % (notef), False)
            new_note = '\n' + new_note
        except:
            pass
        check_both('echo "%s\nGood." >> %s' % (new_note, notef), False)
        check_both('%s %s' % (self.grader.editor, notef))

    def confirm(self):
        print '-----------------------------------------------'
        test = raw_input('OK [y/n]? ').lower() in ['y', '']
        self.pAssertTrue(test)

    def change_cgi(self, new_path):
        self.grader.cgi = new_path

    def liso_name(self):
        name = './lisod'
        # text = raw_input('liso name? ').strip()
        # if text: name = text
        self.liso_name = name
        return name

    def get_path(self):
        path = None
        # text = raw_input('path? ').strip()
        # if text: path = text
        return path

    def get_port(self):
        port = self.port
        # text = raw_input('port? ').strip()
        # if text: port = int(text)
        self.port = port
        print port
        return port

    def get_tls_port(self):
        tls_port = self.tls_port
        # text = raw_input('tls_port? ').strip()
        # if text: tls_port = int(text)
        self.tls_port = tls_port
        print tls_port
        return tls_port

    def find_path(self, name, tree, path='./', d=0):
        if d == 15: return None
        name = name.lower().strip()

        # bredth first...?
        for entry in tree:
            if entry.name.lower().strip() == name:
                return path

        # now check depth...?
        entries = [e for e in tree]
        for entry in reversed(entries):
            obj = self.repository[entry.oid]
            if isinstance(obj, Tree):
                obj = self.find_path(name, obj, os.path.join(path, entry.name),
                                     d + 1)
                if obj:
                    return obj
        return None

    def find_file(self, name, tree, d=0):
        if d == 15: return None
        name = name.lower().strip()

        # bredth first...?
        for entry in tree:
            if entry.name.lower().strip() == name:
                resolved = self.repository[entry.oid]
                if not isinstance(resolved, Blob):
                    continue
                return resolved

        # now check depth...?
        entries = [e for e in tree]
        for entry in reversed(entries):
            obj = self.repository[entry.oid]
            if isinstance(obj, Tree):
                obj = self.find_file(name, obj, d + 1)
                if obj:
                    return obj
        return None

    def run_lisod(self, tree):
        path = self.get_path()
        liso = self.liso_name()
        port = self.get_port()
        tls_port = self.get_tls_port()
        if not path: path = self.find_path('Makefile', tree)
        print 'switching to: %s' % path
        os.chdir(path)
        check_both('make clean', False, False)
        check_output('make')
        self.ran = True
        resource.setrlimit(resource.RLIMIT_STACK,
                           (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
        cmd = '%s %d %d %slisod.log %slisod.lock %s %s %s %s&' % (
            liso, port, tls_port, self.grader.tmp_dir, self.grader.tmp_dir,
            self.grader.www[:-1], self.grader.cgi, self.grader.priv_key,
            self.grader.cert)
        #cmd = 'nohup ' + cmd
        #cmd = cmd + " > /dev/null"
        print cmd
        self.pAssertEqual(0, os.system(cmd))
        return liso

    def git_clone(self, repourl):
        with open('/dev/null', 'w') as f:
            self.pAssertEqual(
                0, check_call(['git', 'clone', repourl], stderr=f, stdout=f))

    def git_checkout(self, commit_hex):
        with open('/dev/null', 'w') as f:
            self.pAssertEqual(
                0,
                check_call(
                    ['git', 'checkout', '%s' % commit_hex], stdout=f,
                    stderr=f))

    def resolve_tag(self):
        try:
            tag = self.repository.lookup_reference('refs/tags/checkpoint-%d' %
                                                   self.grader.cp_num)
        except KeyError:
            try:
                tag = self.repository.lookup_reference(
                    'refs/tags/checkpoint_%d' % self.grader.cp_num)
            except KeyError:
                tag = self.repository.lookup_reference(
                    'refs/tags/checkpoint%d' % self.grader.cp_num)
        #tag = self.repository.lookup_reference('refs/tags/regrade')
        commit = self.repository[tag.target]
        while isinstance(commit, Tag):
            commit = self.repository[commit.target]
        return commit

    def check_headers(self, response_type, headers, length_content, ext):
        self.pAssertEqual(headers['Server'].lower(), 'liso/1.0')

        try:
            datetime.datetime.strptime(headers['Date'],
                                       '%a, %d %b %Y %H:%M:%S %Z')
        except KeyError:
            self.print_str('Bad Date header')
        except:
            self.print_str('Bad Date header: %s' % (headers['Date']))

        self.pAssertEqual(int(headers['Content-Length']), length_content)
        #self.pAssertEqual(headers['Connection'].lower(), 'close')

        if response_type == 'GET' or response_type == 'HEAD':
            header_set = set([
                'connection', 'content-length', 'date', 'last-modified',
                'server', 'content-type'
            ])
            self.pAssertEqual(set(), header_set - set(headers.keys()))
            if headers['Content-Type'].lower() != MIME[ext]:
                self.print_str('MIME got %s expected %s' %
                               (headers['Content-Type'].lower(), MIME[ext]))
            self.pAssertTrue(
                headers['Content-Type'].lower() == MIME[ext]
                or headers['Content-Type'].lower() == MIME['.html'])

            try:
                datetime.datetime.strptime(headers['Last-Modified'],
                                           '%a, %d %b %Y %H:%M:%S %Z')
            except:
                self.print_str('Bad Last-Modified header: %s' %
                               (headers['Last-Modified']))
        elif response_type == 'POST':
            header_set = set(
                ['connection', 'content-length', 'date', 'server'])
            self.pAssertEqual(set(), header_set - set(headers.keys()))
        else:
            self.fail('Unsupported Response Type...')

    # test existence of tag in repo
    def test_tag_checkpoint(self):
        self.print_str('\n\n----- Testing Tag -----')
        self.repository.lookup_reference('refs/tags/checkpoint-%d' %
                                         self.grader.cp_num)

    # test turn in timestamp
    def test_timestamp(self):
        self.print_str('\n\n----- Testing Timestamp -----')
        commit = self.resolve_tag()
        self.print_str('ref/tags/checkpoint-%d: %s' %
                       (self.grader.cp_num, commit.hex))
        self.print_str('Due: %s' % self.grader.due_date)
        utctime = datetime.datetime.utcfromtimestamp(commit.commit_time)
        utcoffset = datetime.timedelta(minutes=commit.commit_time_offset)
        timestamp = utctime + utcoffset
        self.print_str('Timestamp: %s' % timestamp)
        timediff = timestamp - self.grader.due_date
        if timediff.days >= 0 and\
           timediff.seconds > 0 or\
           timediff.microseconds > 0:
            raise ValueError

    # test readme.txt file up to snuff
    def test_readme_file(self):
        self.print_str('\n\n----- Testing readme.txt file -----')
        commit = self.resolve_tag()
        tree = commit.tree
        print '\n----- readme.txt -----'
        readme = self.find_file('readme.txt', tree)
        print readme.data,
        self.confirm()
        self.edit_notes('README:')

    # test vulnerabilities.txt up to snuff
    def test_vulnerabilities_file(self):
        self.print_str('\n\n----- Testing vulnerabilities.txt file -----')
        commit = self.resolve_tag()
        tree = commit.tree
        print '\n----- vulnerabilities.txt -----'
        vulnerable = self.find_file('vulnerabilities.txt', tree)
        print vulnerable.data,
        self.confirm()
        self.edit_notes('VULNERABILITIES:')

    # test tests.txt up to snuff
    def test_tests_file(self):
        self.print_str('\n\n----- Testing tests.txt file -----')
        commit = self.resolve_tag()
        tree = commit.tree
        print '\n----- tests.txt -----'
        tests = self.find_file('tests.txt', tree)
        print tests.data,
        self.confirm()
        self.edit_notes('TESTS:')

    # test Makefile up to snuff
    def test_Makefile_file(self):
        self.print_str('\n\n----- Testing Makefile file -----')
        commit = self.resolve_tag()
        tree = commit.tree
        print '\n----- Makefile -----'
        Makefile = self.find_file('Makefile', tree)
        print Makefile.data,
        self.confirm()
        self.edit_notes('MAKEFILE:')

    # test if source up to snuff
    def test_inspect_source(self):
        self.print_str('\n\n----- Inspect Source cod *.[c|h] -----')
        self.print_str(self.grader.source_reminder)
        self.pAssertEqual(0, check_call(['bash']))
        self.confirm()
        self.edit_notes('SOURCE:')

    # tests if make properly creates lisod...
    def test_lisod_file(self):
        self.print_str('\n\n----- Testing make -----')
        commit = self.resolve_tag()
        path = self.get_path()
        if not path: path = self.find_path('Makefile', commit.tree)
        os.chdir(path)
        check_output('make')
        self.pAssertTrue(os.path.exists('./lisod'))

    # send all test files to their server
    # get output, give 3 second timeout
    # check sha's of output
    def test_replays(self):
        self.print_str('\n\n----- Testing Replays -----')
        commit = self.resolve_tag()
        self.run_lisod(commit.tree)
        time.sleep(3)
        replays_dir = os.path.join(self.grader.tmp_dir, 'replays')
        if not os.path.exists(replays_dir):
            os.makedirs(replays_dir)
        files = os.listdir(replays_dir)
        num_passed = 0
        num_files = 0
        for fname in files:
            basename, extension = os.path.splitext(fname)
            if extension == '.test':
                num_files += 1
                self.print_str('testing %s...' % fname)
                fname = os.path.join(self.grader.tmp_dir + 'replays', fname)
                outfile = os.path.join(self.grader.tmp_dir + 'replays',
                                       '%s_%s.out' % (basename, self.repo))
                command = 'ncat -i 1s localhost %d < %s > %s' % (
                    self.port, fname, outfile)

                check_both(command, False, False)
                with open(
                        os.path.join(self.grader.tmp_dir + 'replays',
                                     basename + '.out')) as f:
                    with open(outfile) as f2:
                        outhash = hashlib.sha256(f.read()).hexdigest()
                        out2hash = hashlib.sha256(f2.read()).hexdigest()
                        if outhash == out2hash:
                            self.print_str('ok')
                            num_passed += 1
                        else:
                            self.print_str('failed')
                check_both('rm %s' % outfile)
        self.print_str('passed %d of %d' % (num_passed, num_files))
        self.pAssertEqual(num_passed, num_files)

    def test_HEAD_headers(self):
        self.print_str('----- Testing Headers -----')
        tests = {
            'http://127.0.0.1:%d/index.html':
            ('f5cacdcb48b7d85ff48da4653f8bf8a7c94fb8fb43407a8e82322302ab13becd',
             802),
            'http://127.0.0.1:%d/images/liso_header.png':
            ('abf1a740b8951ae46212eb0b61a20c403c92b45ed447fe1143264c637c2e0786',
             17431),
            'http://127.0.0.1:%d/style.css':
            ('575150c0258a3016223dd99bd46e203a820eef4f6f5486f7789eb7076e46736a',
             301)
        }
        commit = self.resolve_tag()
        self.git_checkout(commit.hex)
        name = self.run_lisod(commit.tree)
        time.sleep(1)
        for test in tests:
            root, ext = os.path.splitext(test)
            response = requests.head(test % self.port, timeout=10.0)
            self.check_headers(response.request.method, response.headers,
                               tests[test][1], ext)

    def test_HEAD(self):
        self.print_str('----- Testing HEAD -----')
        tests = {
            'http://127.0.0.1:%d/index.html':
            ('f5cacdcb48b7d85ff48da4653f8bf8a7c94fb8fb43407a8e82322302ab13becd',
             802),
            'http://127.0.0.1:%d/images/liso_header.png':
            ('abf1a740b8951ae46212eb0b61a20c403c92b45ed447fe1143264c637c2e0786',
             17431),
            'http://127.0.0.1:%d/style.css':
            ('575150c0258a3016223dd99bd46e203a820eef4f6f5486f7789eb7076e46736a',
             301)
        }
        commit = self.resolve_tag()
        self.git_checkout(commit.hex)
        name = self.run_lisod(commit.tree)
        time.sleep(1)
        for test in tests:
            root, ext = os.path.splitext(test)
            response = requests.head(test % self.port, timeout=10.0)
            contenthash = hashlib.sha256(response.content).hexdigest()
            self.pAssertEqual(200, response.status_code)

    def test_GET(self):
        self.print_str('----- Testing GET -----')
        tests = {
            'http://127.0.0.1:%d/index.html':
            'f5cacdcb48b7d85ff48da4653f8bf8a7c94fb8fb43407a8e82322302ab13becd',
            'http://127.0.0.1:%d/images/liso_header.png':
            'abf1a740b8951ae46212eb0b61a20c403c92b45ed447fe1143264c637c2e0786',
            'http://127.0.0.1:%d/style.css':
            '575150c0258a3016223dd99bd46e203a820eef4f6f5486f7789eb7076e46736a'
        }
        commit = self.resolve_tag()
        self.git_checkout(commit.hex)
        name = self.run_lisod(commit.tree)
        time.sleep(1)
        for test in tests:
            root, ext = os.path.splitext(test)
            response = requests.get(test % self.port, timeout=10.0)
            contenthash = hashlib.sha256(response.content).hexdigest()
            self.pAssertEqual(200, response.status_code)
            self.pAssertEqual(contenthash, tests[test])

    def test_POST(self):
        self.print_str('----- Testing POST -----')
        tests = {
            'http://127.0.0.1:%d/index.html':
            'f5cacdcb48b7d85ff48da4653f8bf8a7c94fb8fb43407a8e82322302ab13becd',
        }
        commit = self.resolve_tag()
        self.git_checkout(commit.hex)
        name = self.run_lisod(commit.tree)
        time.sleep(1)
        for test in tests:
            root, ext = os.path.splitext(test)
            # for checkpoint 2, this should time out; we told them to swallow the data and ignore
            try:
                response = requests.post(test % self.port,
                                         data='dummy data',
                                         timeout=3.0)
            #except requests.exceptions.Timeout:
            except requests.exceptions.RequestException:
                print 'timeout'
                continue
            except socket.timeout:
                print 'socket.timeout'
                continue

            # if they do return something, make sure it's OK
            self.pAssertEqual(200, response.status_code)

    def test_bw(self):
        print '(----- Testing BW -----'
        check_output('echo "----- Testing BW ----" >> %s' %
                     self.grader.results)
        commit = self.resolve_tag()
        self.git_checkout(commit.hex)
        name = self.run_lisod(commit.tree)
        time.sleep(1)
        self.pAssertEqual(
            0,
            os.system(
                'curl -m 10 -o /dev/null http://127.0.0.1:%d/big.html 2>> %s' %
                (self.port, self.grader.results)))

    def tearDown(self):
        #check_both('rm ' + self.grader.tmp_dir + 'lisod.log', False, False)
        check_both('rm ' + self.grader.tmp_dir + 'lisod.lock', False, False)
        os.chdir(self.grader.tmp_dir)
        shutil.rmtree(self.repo)
        if sys.exc_info() == (None, None, None):  #test succeeded
            self.out_string += '\nok'
        else:
            self.out_string += '\nfailed'
        if self.out_string:
            check_both('echo "%s" >> %s' %
                       (self.out_string, self.grader.results))
        if self.ran:
            print 'trying "killall -9 %s"' % os.path.basename(self.liso_name)
            check_both('killall -9 %s' % os.path.basename(self.liso_name),
                       True, False)
Example #51
0
 def test_write_tree_to(self):
     pygit2.option(pygit2.GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, False)
     with utils.TemporaryRepository(('tar', 'emptyrepo')) as path:
         nrepo = Repository(path)
         id = self.repo.index.write_tree(nrepo)
         assert nrepo[id] is not None
Example #52
0
""" Handles all things git (there aren't many of them) """
from pygit2 import discover_repository, Repository
import os

PATH = discover_repository(os.path.dirname(__file__))
REPO = Repository(PATH)
# https://www.pygit2.org/repository.html
Example #53
0
import itertools

parser = argparse.ArgumentParser(description='Run Kiln for every commit on the default branch in a git repo')
parser.add_argument('dir')
parser.add_argument('app_name')
parser.add_argument('data_collector_url')
args = parser.parse_args()
proj_dir = vars(args)['dir']
app_name = vars(args)['app_name']
url = vars(args)['data_collector_url']

repo_path = discover_repository(proj_dir)
if repo_path == None:
    raise Exception("Project directory isn't a git repo. Exiting!")

repo = Repository(repo_path)
default_branch = repo.resolve_refish('origin/HEAD')[1].shorthand
walker = repo.walk(repo.branches[default_branch].peel().id, GIT_SORT_REVERSE | GIT_SORT_TIME)
walker.simplify_first_parent()
all_commits = [x.id for x in walker]
kiln_config_path = os.path.abspath(os.path.join(proj_dir, "kiln.toml"))
for commit in all_commits:
    if commit == "":
        continue
    subprocess.check_call(["git", "reset", "--hard", "HEAD"], cwd=proj_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    subprocess.check_call(["git", "checkout", str(commit)], cwd=proj_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    if not os.path.exists(os.path.abspath(os.path.join(proj_dir, "Gemfile.lock"))):
        print("No Gemfile.lock, skipping commit ", str(commit))
        continue
Example #54
0
import sys
import os
import io
import re
import time

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from distutils.sysconfig import customize_compiler
from distutils.command.build_py import build_py

version = '1.4'
branchversion = version
try:
    from pygit2 import Repository
    head = Repository('.').head.shorthand
    if head != 'master':
        branchversion = version + '.' + head
except:
    Repository = None

print('cmf', branchversion)

# Try to import numpy, if it fails we have a problem
try:
    # Import a function to get a path to the include directories of numpy
    # noinspection PyPackageRequirements
    from numpy import get_include as get_numpy_include
except ImportError:
    raise RuntimeError(
        "For building and running of cmf an installation of numpy is needed")
Example #55
0
def switch_branch(working_dir, branch_name):
    repo = Repository(working_dir + '.git')
    print('switch to: ' + branch_name)
    branch = repo.branches[branch_name]
    repo.checkout('refs/heads/' + branch.branch_name)
Example #56
0
def post(event, context):
    # Logging the entire event is a cheap simple way to make debugging easier
    # Often times just being able to see the event information quickly can help
    # Troubleshoot an issue faster than hooking up a debugger
    logger.info(event)

    # We always want to take the shortest path through our functions. Check for anything fatal first.
    try:
        output_bucket = os.environ['output_bucket']
    except:
        raise Exception(
            'Output Bucket not defined. Set the environment variable for the funcion'
        )

    # Here we take a few steps to get the JSON into the body object
    # If this came in as a proxy request, or a direct API Gateway request
    # or a boto3 invokation the format of the body could be a few different types
    # With this stepped approach we can gaurantee that no matter how this was caled
    # we will have JSON in the body variable.
    if "body" in event:
        body = json.loads(event['body'])
    else:
        try:
            body = json.loads(event)
        except:
            body = event

    # We will still validate this before doing anything with it, but if we are missing
    # any essential components we should end early to save processing time.
    # No point in computing hashes for a payload that is missing data we need.
    try:
        full_name = body['repository']['full_name']
    except KeyError:
        raise Exception('Failed to find full_name in json post body')

    try:
        remote_url = body['repository']['clone_url']
    except KeyError:
        raise Exception('Failed to find clone_url name in json post body')

    try:
        github_secrets = os.environ['github_secrets']
    except:
        raise Exception(
            'Github secrets not defined. Set the environment variable for the funcion'
        )

    if "headers" in event and "X-GitHub-Event" in event['headers']:
        # We only care about push events, if this isn't one politely exit
        if event['headers']['X-GitHub-Event'] != "push":
            return {
                "statusCode": 200,
                "body": json.dumps('Skipping - Not a push event')
            }

    # We split this env variable because we could be re-using this function for multiple API
    # endpoints, multiple repos etc. It is best practice to have a secret per repo
    # so even if we use this exact endpoint we can still feed it multiple repos with multiple
    # keys. We define each key with a , to separate them.
    apikeys = github_secrets.split(',')

    # set a validation key, we will check multiple keys so it holds our result
    secure = False

    # Compute out the hash and validate the signature. If it passes set secure, otherwise throw an error
    if 'X-Hub-Signature' in event['headers'].keys():
        signature = event['headers']['X-Hub-Signature']
        for k in apikeys:
            computed_hash = hmac.new(k.encode('ascii'),
                                     event['body'].encode('ascii'),
                                     hashlib.sha1)
            computed_signature = '='.join(['sha1', computed_hash.hexdigest()])
            hmac.compare_digest(computed_signature.encode('ascii'),
                                signature.encode('ascii'))
            if hmac.compare_digest(computed_signature.encode('ascii'),
                                   signature.encode('ascii')):
                secure = True
    if secure == False:
        raise Exception('Failed to validate authenticity of webhook message')

    repo_name = full_name + '/branch/' + branch_name
    repo_path = '/tmp/%s' % repo_name

    # If we have an existing repo (if this function is still warm / is not a cold start)
    # we can re-use that repo on the file system and update it to save us some time and bandwidth
    try:
        repository_path = discover_repository(repo_path)
        repo = Repository(repository_path)
        logger.info('found existing repo, using that...')
    # If a previous repo is not found we will create it
    except Exception:
        logger.info('creating new repo for %s in %s' % (remote_url, repo_path))
        repo = create_repo(repo_path, remote_url)

    # Re-used or created, we now have a repo reference to pull against
    pull_repo(repo, branch_name, remote_url)

    # Compile the site to our pre-defined path
    build_hugo(repo_path, build_path)

    # Sync the site to our public s3 bucket for hosting
    upload_to_s3(build_path, output_bucket)

    if cleanup:
        logger.info('Cleanup Lambda container...')
        shutil.rmtree(repo_path)

    # We have to return a status code otherwise the API Gateway will give a server error
    # however we are likely exceeding the 29s hard timeout limit on the API gateway
    # but if we can return correctly we should attempt to, that window could be changed later
    # or we could execute in time occassionally
    return {
        "statusCode": 200,
        "body": json.dumps('Successfully updated %s' % repo_name)
    }
Example #57
0
def delete_branch(working_dir, branch_name):
    repo = Repository(working_dir + '.git')
    print branch_name
    repo.branches.delete(branch_name)
Example #58
0
def check(dir):
    repo = Repository(dir + '.git')
    print('Path to the git repository is:', repo.path)
    if not repo.is_bare:
        print('Working directory of the repository is', repo.workdir)
    return repo
Example #59
0
def show_status(srcdir,
                packages,
                projects,
                other_git,
                ws_state,
                show_up_to_date=True,
                cache=None):
    def create_upstream_status(repo, head_branch, master_branch,
                               master_remote_branch, tracking_branch):
        status = []
        if not repo.head_is_detached and not has_pending_merge(repo):
            if tracking_branch is not None:
                if master_remote_branch is not None:
                    if tracking_branch.remote_name != master_remote_branch.remote_name:
                        status.append("@!@{rf}remote '%s'" %
                                      tracking_branch.remote_name)
                if need_push(repo, head_branch):
                    status.append("@!@{yf}needs push")
                elif need_pull(repo, head_branch):
                    status.append("@!@{cf}needs pull")
                elif not is_up_to_date(repo, head_branch):
                    status.append("@!@{yf}needs pull -M")
            else:
                if head_branch:
                    status.append("@!on branch '%s'" % repo.head.shorthand)
                else:
                    status.append("empty branch")
                if master_remote_branch is None:
                    status.append("@!@{rf}no remote")
                elif master_branch is None:
                    status.append("@!@{rf}untracked remote")
                if is_up_to_date(repo, master_branch) or need_push(
                        repo, master_branch):
                    if need_pull(repo, head_branch, master_branch):
                        status.append("@!@{cf}needs pull -L")
                    else:
                        if not is_ancestor(repo, master_branch, head_branch):
                            status.append("@!@{yf}needs merge --from-master")
                        if not is_up_to_date(repo, head_branch, master_branch):
                            status.append("@!@{yf}needs merge --to-master")
            if master_branch is not None and master_remote_branch is not None and (
                    tracking_branch is None
                    or tracking_branch.name != master_remote_branch.name):
                if need_push(repo, master_branch):
                    status.append("@!@{yf}%s needs push" %
                                  master_branch.shorthand)
                elif need_pull(repo, master_branch):
                    status.append("@!@{cf}%s needs pull" %
                                  master_branch.shorthand)
                elif not is_up_to_date(repo, master_branch):
                    status.append("@!@{yf}%s needs merge" %
                                  master_branch.shorthand)
        return status

    def create_local_status(repo, upstream_status, is_dirty):
        status = []
        if repo.head_is_detached:
            status.append("@!@{rf}detached HEAD")
            return status
        if has_pending_merge(repo):
            if repo.index.conflicts:
                status.append("@!@{rf}merge conflicts")
            else:
                status.append("@!@{yf}merged, needs commit")
            return status
        if is_dirty:
            status.append("@!@{yf}needs commit")
        status += upstream_status
        if not status:
            if not show_up_to_date:
                return None
            status.append("@!@{gf}up-to-date")
        return status

    table = TableView("Package", "Path", "Status")

    found_packages = set()
    for project in projects:
        repo = Repository(os.path.join(srcdir, project.workspace_path, ".git"))
        dirty_files = [
            a for a, b in iteritems(repo.status())
            if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT
        ]
        head_branch = get_head_branch(repo)
        tracking_branch = head_branch.upstream if head_branch else None
        master_remote = get_origin(repo, project)
        if master_remote is not None:
            master_remote_branch = repo.lookup_branch(
                "%s/%s" % (master_remote.name, project.master_branch),
                GIT_BRANCH_REMOTE)
            master_branch = None
            if master_remote_branch is not None:
                for name in repo.listall_branches(GIT_BRANCH_LOCAL):
                    b = repo.lookup_branch(name, GIT_BRANCH_LOCAL)
                    if b.upstream and b.upstream.branch_name == master_remote_branch.branch_name:
                        master_branch = b
                        break
        else:
            master_remote_branch = None
            master_branch = None
        ws_packages = find_catkin_packages(srcdir,
                                           project.workspace_path,
                                           cache=cache)
        found_packages |= set(ws_packages.keys())
        upstream_status = create_upstream_status(repo, head_branch,
                                                 master_branch,
                                                 master_remote_branch,
                                                 tracking_branch)
        for name, pkg_list in iteritems(ws_packages):
            if name not in packages:
                continue
            for pkg in pkg_list:
                is_dirty = False
                local_path = os.path.relpath(pkg.workspace_path,
                                             project.workspace_path)
                if dirty_files and local_path == ".":
                    is_dirty = True
                else:
                    for fpath in dirty_files:
                        if path_has_prefix(fpath, local_path):
                            is_dirty = True
                            break
                status = create_local_status(repo, upstream_status, is_dirty)
                if status is not None:
                    head, tail = os.path.split(pkg.workspace_path)
                    pkg_path = escape(head + "/" if tail ==
                                      name else pkg.workspace_path)
                    table.add_row(escape(name), pkg_path, status)

    for path in other_git:
        repo = Repository(os.path.join(srcdir, path, ".git"))
        dirty_files = [
            a for a, b in iteritems(repo.status())
            if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT
        ]
        head_branch = get_head_branch(repo)
        tracking_branch = head_branch.upstream if head_branch else None
        ws_packages = find_catkin_packages(srcdir, path, cache=cache)
        found_packages |= set(ws_packages.keys())
        upstream_status = create_upstream_status(repo, head_branch, None, None,
                                                 tracking_branch)
        for name, pkg_list in iteritems(ws_packages):
            if name not in packages:
                continue
            for pkg in pkg_list:
                is_dirty = False
                local_path = os.path.relpath(pkg.workspace_path, path)
                if dirty_files and local_path == ".":
                    is_dirty = True
                else:
                    for fpath in dirty_files:
                        if path_has_prefix(fpath, local_path):
                            is_dirty = True
                            break
                status = create_local_status(repo, upstream_status, is_dirty)
                if status is not None:
                    head, tail = os.path.split(pkg.workspace_path)
                    pkg_path = escape(head + "/" if tail ==
                                      name else pkg.workspace_path)
                    table.add_row(escape(name), pkg_path, status)

    missing = set(packages) - found_packages
    for name in missing:
        path_list = []
        status = "no git"
        if name in ws_state.ws_packages:
            for pkg in ws_state.ws_packages[name]:
                if not os.path.isdir(os.path.join(srcdir, pkg.workspace_path)):
                    status = "@{rf}deleted"
                head, tail = os.path.split(pkg.workspace_path)
                path_list.append(
                    escape(head + "/" if tail == name else pkg.workspace_path))
        table.add_row(escape(name), path_list, status)
    if table.empty():
        if found_packages:
            msg("Everything is @!@{gf}up-to-date@|.\n")
        else:
            warning("no Git repositories\n")
    else:
        table.sort(0)
        table.write(sys.stdout)
    def __init__(self, buffer_id, config_dir, directory):
        super(GitViewerWidget, self).__init__()

        repo_path = discover_repository(directory)
        if repo_path:
            repo = Repository(repo_path)
            commit_size = 0
            lastest_commit = None
            for commit in repo.walk(repo.head.target, GIT_SORT_TOPOLOGICAL):
                commit_size += 1

                if not lastest_commit:
                    lastest_commit = commit

            remote_branch_size = 0
            for branch in repo.branches.remote:
                if branch != "origin/HEAD" and branch != "origin/master":
                    remote_branch_size += 1

            # Change background.
            self.setStyleSheet("background-color: #000000")

            # Add main box.
            main_box = QVBoxLayout()
            main_box.setSpacing(0)
            main_box.setContentsMargins(0, 0, 0, 0)

            self.setLayout(main_box)

            # Add repo top area.
            self.repo_top_font_size = 18
            self.repo_top_area = QWidget()
            self.repo_top_layout = QVBoxLayout()
            self.repo_top_layout.setSpacing(0)
            self.repo_top_layout.setContentsMargins(30, 30, 30, 30)
            self.repo_top_area.setLayout(self.repo_top_layout)
            main_box.addWidget(self.repo_top_area)

            # Add repo title.
            self.repo_title = QLabel(repo.path)
            self.repo_title.setStyleSheet("QLabel {color: #E98123;}")
            self.repo_title.setFont(QFont('Arial', 20))
            self.repo_top_layout.addWidget(self.repo_title)

            # Add summary info.
            self.repo_summary_area = QWidget()
            self.repo_summary_layout = QHBoxLayout()
            self.repo_summary_layout.setSpacing(30)
            self.repo_summary_layout.setContentsMargins(0, 0, 0, 0)
            self.repo_summary_area.setLayout(self.repo_summary_layout)
            self.repo_top_layout.addWidget(self.repo_summary_area)

            # Add head info.
            self.head_info = QLabel("{}    {}    {}    {}".format(
                repo.head.shorthand,
                str(remote_branch_size) + " branches",
                str(commit_size) + " commits",
                format_bytes(get_dir_size(repo_path))))
            self.head_info.setStyleSheet("QLabel {color: #C46C1D;}")
            self.head_info.setFont(QFont('Arial', self.repo_top_font_size))
            self.repo_summary_layout.addWidget(self.head_info)

            self.repo_summary_layout.addStretch(1)

            # Add lastest commit info.
            self.lastest_commit_area = QWidget()
            self.lastest_commit_layout = QHBoxLayout()
            self.lastest_commit_layout.setSpacing(30)
            self.lastest_commit_layout.setContentsMargins(0, 30, 0, 30)
            self.lastest_commit_area.setLayout(self.lastest_commit_layout)
            self.repo_top_layout.addWidget(self.lastest_commit_area)

            self.lastest_commit_info = QLabel(
                "Lastest: {}    {}...    {}    {}".format(
                    lastest_commit.author.name,
                    lastest_commit.message.split("\n")[0][:40],
                    lastest_commit.hex[:7],
                    datetime.utcfromtimestamp(
                        lastest_commit.author.time).strftime(
                            '%Y-%m-%d %H:%M:%S')))
            self.lastest_commit_info.setStyleSheet("QLabel {color: #6C6C6C;}")
            self.lastest_commit_info.setFont(
                QFont('Arial', self.repo_top_font_size))
            self.lastest_commit_layout.addWidget(self.lastest_commit_info)

            self.lastest_commit_layout.addStretch(1)

            # Add info box.
            info_box = QWidget()
            info_area_layout = QHBoxLayout()
            info_area_layout.setSpacing(30)
            info_area_layout.setContentsMargins(30, 0, 30, 30)
            info_box.setLayout(info_area_layout)

            # Add category panel.
            category_panel_listview = QListView()
            category_panel_listview.setSpacing(10)
            category_panel_listview.setStyleSheet(
                "QListView {font-size: 40px;}")
            category_panel_model = QStringListModel()
            category_panel_list = ["Status", "Commit", "Branch", "Submodule"]
            category_panel_model.setStringList(category_panel_list)
            category_panel_listview.setModel(category_panel_model)

            info_area_layout.addWidget(category_panel_listview)
            info_area_layout.setStretchFactor(category_panel_listview, 1)

            # Add view panel.
            view_panel_listview = QListView()
            view_panel_listview.setSpacing(10)
            view_panel_listview.setStyleSheet("QListView {font-size: 40px;}")
            view_panel_model = QStringListModel()
            view_panel_list = ["Current repo update to date."]
            view_panel_model.setStringList(view_panel_list)
            view_panel_listview.setModel(view_panel_model)

            info_area_layout.addWidget(view_panel_listview)
            info_area_layout.setStretchFactor(view_panel_listview, 4)

            # Add help panel.
            help_panel_listview = QListView()
            help_panel_listview.setSpacing(10)
            help_panel_listview.setStyleSheet("QListView {font-size: 40px;}")
            help_panel_model = QStringListModel()
            help_panel_list = [
                "Press l: Git pull", "Press u: Git push",
                "Press a: Commit all", "Press s: Commit file",
                "Press k: Cancel file"
            ]
            help_panel_model.setStringList(help_panel_list)
            help_panel_listview.setModel(help_panel_model)

            info_area_layout.addWidget(help_panel_listview)
            info_area_layout.setStretchFactor(help_panel_listview, 1)

            main_box.addWidget(info_box)