<commit_before>#!/usr/bin/env python
"""
Scripts for retrieving data about the git repository
"""

from git import *
import os, sys
import gitstatus
import json

def get_repo(dirpath):
    """
    Validates whether the script was run in a git repository,
    then returns the pygit2 Repo object
    """
    git_directory = os.path.join(dirpath + "/.git/")

    if not os.path.exists(git_directory):
        print "We couldn't find a .git/ directory in the current working directory. Are you in the root of the git repository?"
        sys.exit(1)    
    elif not os.path.isdir(git_directory):
        print "We found a file named .git/, but it should be a directory."
        sys.exit(1)

    return Repo.init(dirpath)


def get_computer_info(dirpath):
    """
    TODO
    """
    repo = get_repo(dirpath)

    # Read in git config
    config = repo.config_reader()
    user_name = config.get_value("user", "name")
    user_email = config.get_value("user", "email")
    origin_remote, remote_url = _get_remote_origin(repo)

    computer = {
        "name": user_name,
        "email": user_email,
        "remoteUrl": remote_url
    }
    
    return computer


def get_working_copy(params, dirpath):
    """
    Returns:
    """
    repo = get_repo(dirpath)

    # Gather branch information
    current_branch = repo.active_branch
    untracked = repo.untracked_files

    # In order to make sure that we have up to date information, we fetch
    origin_remote, remote_url = _get_remote_origin(repo)
    origin_remote.fetch()

    # Gather information about unpushed commits
    unpushed_commits = {}

    raw_unpushed_str = repo.git.log("origin/%s..HEAD" % current_branch.name)
    unpushed_hexshas = [line.split(" ")[1] for line in raw_unpushed_str.split('\n') 
            if line.startswith("commit")]
    unpushed_objs = [repo.commit(h) for h in unpushed_hexshas]

    if unpushed_objs:
        previous_commit = unpushed_objs[-1].parents[0] # First parent commit
    else:
        previous_commit = None

    unpushed_commits = []
    for u in unpushed_objs:
        unpushed_commits.append(_commit_to_dict(u, previous_commit))
        previous_commit = u

    # Information about the commits on that branch
    # Grab the commits in reverse chronological order
    # TODO: Deprecate "all commits" when we're sure it's no longer needed
    commits = []
    previous_commit = None  # Find diff relative to previous commit
    for c in repo.iter_commits():
        commit_info = _commit_to_dict(c, previous_commit)
        commits.append(commit_info)
        previous_commit = c

    # Pull statistics from the zsh git plugin (i.e. number of untracked)
    file_stats = gitstatus.get_statistics(dirpath)

    # Unstaged changes for added files (aka git diff)
    current_diffs_raw = repo.index.diff(None, create_patch=True)
    current_diffs = _difflist_to_dictlist(current_diffs_raw)

    working_copy = {
            "computerId": params["computerId"],
            "branchName": current_branch.name,
            "remoteUrl": remote_url,
            "untrackedFiles": untracked,
            "unpushedCommits": unpushed_commits,
            "clientDir": dirpath,
            "fileStats": file_stats,
            "gitDiff": current_diffs
    }

    return working_copy

def _commit_to_dict(c, previous_commit=None):
    """ 
    Converts a commit object to a dict that we can send to the server i

    Args: 
        c: pygit2 commit object
        previous_commit: another pygit2 commit object, used
            to find a diff<commit_msg>commented out code related to git diff<commit_after>#!/usr/bin/env python
"""
Scripts for retrieving data about the git repository
"""

from git import *
import os, sys
import gitstatus
import json

def get_repo(dirpath):
    """
    Validates whether the script was run in a git repository,
    then returns the pygit2 Repo object
    """
    git_directory = os.path.join(dirpath + "/.git/")

    if not os.path.exists(git_directory):
        print "We couldn't find a .git/ directory in the current working directory. Are you in the root of the git repository?"
        sys.exit(1)    
    elif not os.path.isdir(git_directory):
        print "We found a file named .git/, but it should be a directory."
        sys.exit(1)

    return Repo.init(dirpath)


def get_computer_info(dirpath):
    """
    TODO
    """
    repo = get_repo(dirpath)

    # Read in git config
    config = repo.config_reader()
    user_name = config.get_value("user", "name")
    user_email = config.get_value("user", "email")
    origin_remote, remote_url = _get_remote_origin(repo)

    computer = {
        "name": user_name,
        "email": user_email,
        "remoteUrl": remote_url
    }
    
    return computer


def get_working_copy(params, dirpath):
    """
    Returns:
    """
    repo = get_repo(dirpath)

    # Gather branch information
    current_branch = repo.active_branch
    untracked = repo.untracked_files

    # In order to make sure that we have up to date information, we fetch
    origin_remote, remote_url = _get_remote_origin(repo)
    origin_remote.fetch()

    # Gather information about unpushed commits
    unpushed_commits = {}

    raw_unpushed_str = repo.git.log("origin/%s..HEAD" % current_branch.name)
    unpushed_hexshas = [line.split(" ")[1] for line in raw_unpushed_str.split('\n') 
            if line.startswith("commit")]
    unpushed_objs = [repo.commit(h) for h in unpushed_hexshas]

    if unpushed_objs:
        previous_commit = unpushed_objs[-1].parents[0] # First parent commit
    else:
        previous_commit = None

    unpushed_commits = []
    for u in unpushed_objs:
        unpushed_commits.append(_commit_to_dict(u, previous_commit))
        previous_commit = u

    # Information about the commits on that branch
    # Grab the commits in reverse chronological order
    # TODO: Deprecate "all commits" when we're sure it's no longer needed
    commits = []
    previous_commit = None  # Find diff relative to previous commit
    for c in repo.iter_commits():
        commit_info = _commit_to_dict(c, previous_commit)
        commits.append(commit_info)
        previous_commit = c

    # Pull statistics from the zsh git plugin (i.e. number of untracked)
    file_stats = gitstatus.get_statistics(dirpath)

    # Unstaged changes for added files (aka git diff)
    # current_diffs_raw = repo.index.diff(None, create_patch=True)
    # current_diffs = _difflist_to_dictlist(current_diffs_raw)
    current_diffs = []

    working_copy = {
            "computerId": params["computerId"],
            "branchName": current_branch.name,
            "remoteUrl": remote_url,
            "untrackedFiles": untracked,
            "unpushedCommits": unpushed_commits,
            "clientDir": dirpath,
            "fileStats": file_stats,
            "gitDiff": current_diffs
    }

    return working_copy

def _commit_to_dict(c, previous_commit=None):
    """ 
    Converts a commit object to a dict that we can send to the server i

    Args: 
        c: pygit2 commit object
        previous_commit: another pygit2 commit object, used
            to find a diff
{'fraction_non_alphanumeric': 0.08863063567628116, 'fraction_numerical': 0.0022402688322598714, 'mean_word_length': 2.8361976369495165, 'pattern_counts': {'":': 22, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2855957', 'n_tokens_mistral': 2240, 'n_tokens_neox': 2177, 'n_words': 626}