示例#1
0
def tree_to_github(
    tree: git.Tree, target_subdir: str, gh_repo: GithubRepo
) -> Dict[str, InputGitTreeElement]:
    """Extrae los contenidos de un commit de Git en formato Tree de Github.

    Returns:
      un diccionario donde las claves son rutas en el repo, y los valores
      el InputGitTreeElement que los modifica.
    """
    odb = tree.repo.odb
    target_subdir = target_subdir.rstrip("/") + "/"
    entries = traverse_tree_recursive(odb, tree.binsha, target_subdir)
    contents = {}

    for sha, mode, path in entries:
        # TODO: get exclusion list from repos.yml
        if path.endswith("README.md"):
            continue
        fileobj = io.BytesIO()
        stream_copy(odb.stream(sha), fileobj)
        fileobj.seek(0)
        try:
            text = fileobj.read().decode("utf-8")
            input_elem = InputGitTreeElement(path, f"{mode:o}", "blob", text)
        except UnicodeDecodeError:
            # POST /trees solo permite texto, hay que crear un blob para binario.
            fileobj.seek(0)
            data = base64.b64encode(fileobj.read())
            blob = gh_repo.create_git_blob(data.decode("ascii"), "base64")
            input_elem = InputGitTreeElement(path, f"{mode:o}", "blob", sha=blob.sha)
        finally:
            contents[path] = input_elem

    return contents
示例#2
0
 def get_tree_elements(
     self, sync_state: ContentSyncState, data: str, filepath: str
 ) -> List[InputGitTreeElement]:
     """
     Return the required InputGitTreeElements for a modified ContentSyncState
     """
     tree_elements = []
     # Update with the new file data only if the content isn't deleted
     if sync_state.content.deleted is None:
         tree_elements.append(InputGitTreeElement(filepath, "100644", "blob", data))
     if sync_state.data is None:
         return tree_elements
     # Remove the old filepath stored in the sync state data
     if (
         # If it has been deleted
         sync_state.content.deleted is not None
         or (
             # If it doesn't match current path
             sync_state.data.get(GIT_DATA_FILEPATH, None)
             and sync_state.data[GIT_DATA_FILEPATH] != filepath
         )
     ):
         tree_elements.append(
             InputGitTreeElement(
                 sync_state.data[GIT_DATA_FILEPATH],
                 "100644",
                 "blob",
                 sha=None,
             )
         )
     return tree_elements
示例#3
0
def add_files(repo, branch, message, files):
    """
    Add a new file to a new branch in a GitHub repo
    """

    # Get commit then git commit (not sure about the difference)
    commit = repo.get_branch('master').commit
    git_commit = repo.get_git_commit(commit.sha)

    # We need to include all the files in the master branch
    tree_input = []
    for element in repo.get_git_tree(commit.sha).tree:
        tree_input.append(InputGitTreeElement(element.path,
                                              element.mode,
                                              element.type,
                                              sha=element.sha))

    # We now make a blob with the new file contents and add it to the tree
    for filename, content in files.items():
        content, encoding = content
        blob = repo.create_git_blob(content=content, encoding=encoding)
        tree_input.append(InputGitTreeElement(filename, "100644", "blob", sha=blob.sha))

    # We make a new tree, commit, and branch
    tree = repo.create_git_tree(tree=tree_input)
    commit = repo.create_git_commit(tree=tree, message=message, parents=[git_commit])
    ref = repo.create_git_ref(ref="refs/heads/{0}".format(branch), sha=commit.sha)
    return ref, commit
    def _commit(self,
                filename,
                content,
                message,
                branch,
                remove_trailing_whitespaces=True):
        """
        """
        head_ref = self._repo.get_git_ref("heads/%s" % branch)
        latest_commit = self._repo.get_git_commit(head_ref.object.sha)
        base_tree = latest_commit.tree

        if remove_trailing_whitespaces:
            content = '\n'.join(
                [line.rstrip() for line in content.split('\n')])

        new_tree = self._repo.create_git_tree([
            InputGitTreeElement(
                path="%s" % os.path.join(self._repository_path, filename),
                mode="100644",
                type="blob",
                content=content)
        ], base_tree)

        new_commit = self._repo.create_git_commit(message=message,
                                                  parents=[latest_commit],
                                                  tree=new_tree)

        head_ref.edit(sha=new_commit.sha, force=False)
示例#5
0
def toGithub(filename):
    #    from github import Github
    #    from github import InputGitTreeElement
    location = '/Users/sophiahoenig/HackHer/' + filename
    user = "******"
    password = "******"
    g = Github(user, password)
    repo = g.get_user().get_repo('shoenig17.github.io')
    file_list = [location]
    file_names = [filename]
    commit_message = filename
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    for i, entry in enumerate(file_list):
        with open(entry) as input_file:
            data = input_file.read()
        if entry.endswith('.mp3'):
            data = base64.b64encode(data)
        element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
        element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)
def download_data_and_commit():
    os.system("python3 get_data.py 1")

    REPO_NAME = "OneFourthLabs/COVID-Viz"
    user = "******"
    password = "******"

    g = Github(user, password)
    repo = g.get_repo(REPO_NAME, lazy=False)
    file_list = ["india_states.csv", "india_states_daily.csv"]

    file_names = ["india_states.csv", "india_states_daily.csv"]
    commit_message = 'Update files ' + \
        str(datetime.datetime.now().strftime("%d-%m-%Y %H:%M"))
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    for i, entry in enumerate(file_list):
        with open(entry) as input_file:
            data = input_file.read()
        if entry.endswith('.png'):
            data = base64.b64encode(data)
        element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
        element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)
示例#7
0
    def update(self):
        user = "******"
        password = "******"
        g = Github(user, password)
        repo = g.get_user().get_repo('ABI_test_site')
        file_list = [
            'data.js',
        ]

        file_names = [
            'data.js',
        ]

        commit_message = 'python update'
        master_ref = repo.get_git_ref('heads/master')
        master_sha = master_ref.object.sha
        base_tree = repo.get_git_tree(master_sha)
        element_list = list()
        for i, entry in enumerate(file_list):
            with open(entry) as input_file:
                data = input_file.read()
            if entry.endswith('.png'):
                data = base64.b64encode(data)
            element = InputGitTreeElement(file_names[i], '100644', 'blob',
                                          data)
            element_list.append(element)
        tree = repo.create_git_tree(element_list, base_tree)
        parent = repo.get_git_commit(master_sha)
        commit = repo.create_git_commit(commit_message, tree, [parent])
        master_ref.edit(commit.sha)
示例#8
0
文件: views.py 项目: kom3/techynotes
def push_to_git(request):
    user = os.getenv("GITUNAME")
    password = os.getenv("GITPASS")
    g = Github(user, password)
    repo = g.get_user().get_repo('_techynotes')
    html_list = []
    file_names = []
    source = os.path.join(os.path.abspath("."), "mainscreen", "mynotes")
    file_list = list(os.listdir(source))
    for file in file_list:
        if file.endswith(".html"):
            html_list.append(
                os.path.join(os.path.abspath("."), "mainscreen", "mynotes",
                             file))
            file_names.append(file)
    commit_message = 'created on ' + today.strftime("%d/%m/%Y")
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    for i, entry in enumerate(html_list):
        with open(entry) as input_file:
            data = input_file.read()
        if entry.endswith('.png'):
            data = base64.b64encode(data)
        element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
        element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)
示例#9
0
def commiter(dirPath):
    g = Github(cred['user'], cred['passw'])
    repo = g.get_repo('heIlo-world/hello-world')

    fileList = [
        '{}/text.txt'.format(dirPath),
    ]
    fileNames = [
        'text.txt',
    ]
    commitMessage = '-'
    masterRef = repo.get_git_ref('heads/master')
    masterSha = masterRef.object.sha
    baseTree = repo.get_git_tree(masterSha)
    elementList = list()

    for idx, entry in enumerate(fileList):
        with open(entry) as inputFile:
            data = inputFile.read()

        element = InputGitTreeElement(fileNames[idx], '100644', 'blob', data)
        elementList.append(element)

    tree = repo.create_git_tree(elementList, baseTree)
    parent = repo.get_git_commit(masterSha)
    commit = repo.create_git_commit(commitMessage, tree, [parent])
    masterRef.edit(commit.sha)
示例#10
0
def githup_upload(file_name: str, shorten=True):
    from github import Github, InputGitTreeElement

    _token = decode('GIT_TOKEN')
    g = Github(_token, timeout=300)
    repo = g.get_user().get_repo('stuff')
    data = base64.b64encode(open(file_name, "rb").read())
    blob = repo.create_git_blob(data.decode("utf-8"), "base64")
    path = f'2021/{file_name}'
    element = InputGitTreeElement(path=path,
                                  mode='100644',
                                  type='blob',
                                  sha=blob.sha)
    element_list = list()
    element_list.append(element)

    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(f"Uploading {file_name }", tree, [parent])
    master_ref.edit(commit.sha)

    if shorten:
        url_long = f"{decode('GIT_RAW_PREFIX')}{path}"
        print("Long url:  ", url_long)
        print("Short url: ", git_io_shorten(url_long))
示例#11
0
def push_to_github():
    try:
        file_list = glob.glob(os.path.join(DATAFOLDER, "*.csv"))
        item_list = [x[-14:] for x in file_list]

        file_list.append(os.path.join(DATAFOLDER, "report.json"))
        item_list.extend(["report.json"])
        TOKEN = os.getenv("GHTOKEN")
        g = Github(TOKEN)
        nrepo = g.get_user().get_repo(REPO_NAME)
        commit_msg = ":bug: {}".format(
            datetime.now(pytz.timezone("Asia/Kolkata")).isoformat())
        master_ref = nrepo.get_git_ref("heads/master")
        master_sha = master_ref.object.sha
        base_tree = nrepo.get_git_tree(master_sha)
        elist = []
        for i, entry in enumerate(file_list):
            with open(entry) as input_file:
                data = input_file.read()
            elem = InputGitTreeElement("data/" + item_list[i], '100644',
                                       'blob', data)
            elist.append(elem)
        tree = nrepo.create_git_tree(elist)
        parent = nrepo.get_git_commit(master_sha)
        commit = nrepo.create_git_commit(commit_msg, tree, [parent])
        master_ref.edit(commit.sha)
        # print(elist)
        return True
    except Exception as e:
        print(e)
        logger.error(e)
        return False
def pushGithub(repo,resultadoPath,message):

    g = Github('TOKEN GITREPO')

    repo = g.get_user().get_repo(repo)
    file_list = [resultadoPath]
    #borramos el archivo primero
    try:
        contents = repo.get_contents(resultadoPath, ref="master")
        repo.delete_file(contents.path, "Eliminamos archivo", contents.sha, branch="master")
    except:
        delete=0

    file_names = [resultadoPath]
    commit_message = message

    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    for i, entry in enumerate(file_list):
        with open(entry) as input_file:
            data = input_file.read()
        #if entry.endswith('.png'):
        #    data = base64.b64encode(data)
        element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
        element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)

    return True
示例#13
0
    def make_commit(self, repo, version, user):
        filename = u'checkouts.cfg'
        head_ref = repo.get_git_ref(f'heads/{version}')
        checkouts_cfg_file = repo.get_file_contents(filename,
                                                    head_ref.object.sha)
        line = f'    {self.repo_name}\n'
        checkouts_content = checkouts_cfg_file.decoded_content.decode()
        checkouts_new_data = checkouts_content + line
        latest_commit = repo.get_git_commit(head_ref.object.sha)
        base_tree = latest_commit.tree
        mode = [t.mode for t in base_tree.tree if t.path == filename]
        if mode:
            mode = mode[0]
        else:
            mode = '100644'

        element = InputGitTreeElement(
            path=filename,
            mode=mode,
            type=checkouts_cfg_file.type,
            content=checkouts_new_data,
        )
        new_tree = repo.create_git_tree([element], base_tree)

        new_commit = repo.create_git_commit(
            f'[fc] Add {self.repo_name} to {filename}',
            new_tree,
            [latest_commit],
            user,
            user,
        )
        head_ref.edit(sha=new_commit.sha, force=False)
示例#14
0
    def git_commit(self, file_list, file_names, commit_message):
        '''
        To commit the files to git repo.
        Path to the file, file name and commit message
        is passed as the parameters
        '''
        try:
            master_ref = repo.get_git_ref('heads/master')
            master_sha = master_ref.object.sha
            base_tree = repo.get_git_tree(master_sha)
            element_list = list()

            for i, entry in enumerate(file_list):
                with open(entry) as input_file:
                    data = input_file.read()
                element = InputGitTreeElement(file_names[i], '100644', 'blob',
                                              data)
                element_list.append(element)
            tree = repo.create_git_tree(element_list, base_tree)
            parent = repo.get_git_commit(master_sha)
            commit = repo.create_git_commit(commit_message, tree, [parent])
            master_ref.edit(commit.sha)
            print("commited to the repo")

        except Exception as err:
            print(type(err))
            print(err.args)
            print(err)
示例#15
0
def deleted_files(
    new_files: Set[str],
    cur_tree: GithubTree,
    match_re: re.Pattern = None,
    preserve_from: GithubTree = None,
) -> List[InputGitTreeElement]:
    """Calcula los archivos a borrar en el repositorio junto con la entrega.

    Dada una lista que representa los contenidos actuales de la nueva
    entrega, y dado el árbol existente, esta función calcula los archivos
    que deben ser borrados, y los devuelve en una lista. (Para borrar
    un archivo a través de la API de Github, lo que se necesita es un
    InputGitTreeElement con sha=None.)

    La expresión regular `match_re` se usa para filtrar los subdirectorios
    sobre los que procesar los borrados. Si se especifica `preserve_from`,
    nunca se borrarán archivos que estén presentes en ese árbol.
    """

    def filter_tree(t: GithubTree) -> Set[str]:
        return {
            e.path
            for e in t.tree
            if e.type == "blob" and (not match_re or match_re.match(e.path))
        }

    cur_files = filter_tree(cur_tree)
    preserve_files = filter_tree(preserve_from) if preserve_from else set()

    deletions = cur_files - new_files - preserve_files
    return [InputGitTreeElement(path, "100644", "blob", sha=None) for path in deletions]
示例#16
0
 def publish(self, filename):
     g = Github(self.token)
     repo = g.get_user().get_repo(self.repo)
     file_list = [filename]
     commit_message = 'Add spider result'
     master_ref = repo.get_git_ref('heads/master')
     master_sha = master_ref.object.sha
     base_tree = repo.get_git_tree(master_sha)
     element_list = list()
     for entry in file_list:
         with open(entry, 'r') as input_file:
             data = input_file.read()
         element = InputGitTreeElement(entry, '100644', 'blob', data)
         element_list.append(element)
     tree = repo.create_git_tree(element_list, base_tree)
     parent = repo.get_git_commit(master_sha)
     commit = repo.create_git_commit(commit_message, tree, [parent])
     master_ref.edit(commit.sha)
     """ An egregious hack to change the PNG contents after the commit """
     for entry in file_list:
         with open(entry, 'rb') as input_file:
             data = input_file.read()
         if entry.endswith('.png'):
             old_file = repo.get_contents(entry)
             commit = repo.update_file('/' + entry, 'Update PNG content',
                                       data, old_file.sha)
示例#17
0
 def ip11(message):
     ip111 = open('Transaction.txt', 'a')
     ip111.write(message.text)
     #Push to GitHub
     user = "******"
     password = "******"
     g = Github(user, password)
     repo = g.get_user().get_repo('change')
     file_list = ['Transaction.txt']
     file_names = ['Transaction.txt']
     commit_message = 'New payment'
     master_ref = repo.get_git_ref('heads/master')
     master_sha = master_ref.object.sha
     base_tree = repo.get_git_tree(master_sha)
     element_list = list()
     for i, entry in enumerate(file_list):
         with open(entry) as input_file:
             data = input_file.read()
         element = InputGitTreeElement(file_names[i], '100644', 'blob',
                                       data)
         element_list.append(element)
     tree = repo.create_git_tree(element_list, base_tree)
     parent = repo.get_git_commit(master_sha)
     commit = repo.create_git_commit(commit_message, tree, [parent])
     master_ref.edit(commit.sha)
def daily_github_upload(sub_to_repo):
    # Create a Github object that we can use to connect to Github and do work.
    # It must be initialized with a 40-character secret key. You generate this
    # on Github itself.
    g = Github('****************************************')
    # Copy the location to a local variable.
    current_subdir = sub_to_repo
    # Extract the subdirectory name - this will be the Repo name.
    title = current_subdir[current_subdir.rindex("\\") + 1:]
    # Create Repo through Github object. We will not work on the repo object.
    repo = g.get_user().create_repo(title)
    # Initialize with a README.MD file. You can configure this as needed.
    repo.create_file(
        "README.MD", "A readme file",
        "This was an auto-upload on " + str(datetime.datetime.now()))
    # The message we will add under the commit.
    commit_message = "This was automatically committed."
    # Create a list of file objects.
    file_list = []
    # Create a list of file names.
    file_names = []
    # Do a walk through the subdirectory.
    for subdir, dirs, files in os.walk(current_subdir):
        # For the files in the subdirectory, print them and then add them to
        # list we created, along with the name to the other list.
        for file in files:
            print(os.path.join(subdir, file))
            file_list.append(os.path.join(subdir, file))
            file_names.append(file)
    # Get the branch to add to.
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    # Create an empty list to add files to.
    element_list = list()
    # For each file in list of file objects, read and adjust as needed.
    for i, entry in enumerate(file_list):
        # If normal file type.
        with open(entry) as input_file:
            data = input_file.read()
        # If proprietary file type, encode it.
        if entry.endswith('.png' or '.pdf' or '.xlsx'):
            data = base64.b64encode(data)
        # Put each file that was encoded from above into an appropriate format
        # to add to a branch.
        element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
        # Append the object created above to the list made before the loop.
        element_list.append(element)
    # Create a tree with the elements and specify settings to add the element
    # list to the repo.
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    # Commit!
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)
    # Remove the subdirectory from the folder so we don't repeat.
    shutil.rmtree(current_subdir)
示例#19
0
def commit_updated_posts(fronted_posts_by_path, silos):
    """
    Returns the response of committing the (presumably changed) given posts to
    the remote GITHUB_REF of this repo by following the recipe outlined here:

        https://developer.github.com/v3/git/

    1. Get the current commit object
    2. Retrieve the tree it points to
    3. Retrieve the content of the blob object that tree has for that
       particular file path
    4. Change the content somehow and post a new blob object with that new
       content, getting a blob SHA back
    5. Post a new tree object with that file path pointer replaced with your
       new blob SHA getting a tree SHA back
    6. Create a new commit object with the current commit SHA as the parent
       and the new tree SHA, getting a commit SHA back
    7. Update the reference of your branch to point to the new commit SHA
    """
    if not fronted_posts_by_path:
        action_log("All good: already marked.")
        return None
    if not os.getenv("GITHUB_TOKEN"):
        raise ValueError("missing GITHUB_TOKEN")
    if not os.getenv("GITHUB_REPOSITORY"):
        raise ValueError("missing GITHUB_REPOSITORY")
    if not os.getenv("GITHUB_REF"):
        raise ValueError("missing GITHUB_REF")

    parent = parent_sha()
    # Create a new tree with our updated blobs.
    new_tree = repo().create_git_tree(
        [
            InputGitTreeElement(
                path,
                mode=
                '100644',  # 'file', @see https://developer.github.com/v3/git/trees/#tree-object
                type='blob',
                content=frontmatter.dumps(fronted_post))
            for path, fronted_post in fronted_posts_by_path.items()
        ],
        base_tree=repo().get_git_tree(parent))

    # Commit the new tree.
    new_commit = repo().create_git_commit(
        f'(syndicate): adding IDs for {silos}', new_tree,
        [repo().get_git_commit(parent)])
    # Poosh it.
    ref_name = os.getenv('GITHUB_REF').lstrip('refs/')
    try:
        repo().get_git_ref(ref_name).edit(new_commit.sha)
    except github.GithubException as err:
        action_error(f"Failed to mark syndicated posts: {err}")
        return None
    ## NOTE Need to update the reference SHA for future workflow steps.
    action_setenv('SYNDICATE_SHA', new_commit.sha)
    action_log("Syndicate posts marked.")
def upload_to_github(console, file_list, file_names):
    user = "******"
    with open(directory + "/codigo_github.txt") as github_code_read:
        lines = github_code_read.read().splitlines()
    github_code_read.close()
    password = lines[0]
    github = Github(user, password)
    repo = github.get_user().get_repo('Console-news-on-consoles')

    commit_message = console + " What's New XML update"
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    for i, entry in enumerate(file_list):
        if entry.endswith('.png') or entry.endswith('.jpg') or entry.endswith(
                '.bmp'
        ) or entry.endswith(
                '.gif'
        ):  # Or ZIPs or something like that (think it must have binary content or something)
            data = base64.b64encode(open(entry, "rb").read())
            blob = repo.create_git_blob(data.decode("utf-8"), "base64")
            element = InputGitTreeElement(path=file_names[i],
                                          mode='100644',
                                          type='blob',
                                          sha=blob.sha)
            element_list.append(element)
        else:
            with open(entry) as input_file:
                data = input_file.read()
            input_file.close()
            element = InputGitTreeElement(file_names[i], '100644', 'blob',
                                          data)
            element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)

    print()
    print("--> " + console + " XML updated!")
示例#21
0
 def _create_input_tree(filename,repo,
                        base_tree=GithubObject.NotSet,
                        mode="100644"):
     """ generate a GitTreeElement for a file (a Git commit is 1 or more GitTreeElements)
     :param filename: full path of the file
     :repo : Repository
     :rtype: GitTreeElement
     """
     file_str = os_file_to_string(filename)
     return repo.create_git_tree([InputGitTreeElement(filename,mode,
                                               "blob",file_str)],
                                 base_tree=base_tree)
示例#22
0
 def batch_delete_files(self, paths: List[str], user: Optional[User] = None):
     """Batch delete multiple git files in a single commit"""
     tree_elements = [
         InputGitTreeElement(
             path,
             "100644",
             "blob",
             sha=None,
         )
         for path in paths
     ]
     if tree_elements:
         self.commit_tree(tree_elements, user)
示例#23
0
    def modify_and_branch(self, base_branch, new_branch_name, commit_message, filename, file_content):
        """Create a new branch from base_branch, makes changes to a file, and
        commits it to the new branch."""

        base_sha = self._github.get_git_ref('heads/{}'.format(base_branch)).object.sha
        base_tree = self._github.get_git_tree(base_sha)
        element = InputGitTreeElement(filename, '100644', 'blob', file_content)
        tree = self._github.create_git_tree([element], base_tree)

        parent = self._github.get_git_commit(base_sha)
        commit = self._github.create_git_commit(commit_message, tree, [parent])

        self._github.create_git_ref('refs/heads/{}'.format(new_branch_name), commit.sha)
示例#24
0
def update(repo_path, file_name, content, message):
    g = Github(settings.RAYTER_GITHUB_TOKEN)
    repo = g.get_repo(repo_path)
    master_ref = repo.get_git_ref("heads/master")
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    element = InputGitTreeElement(file_name, "100644", "blob", content)
    element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(message, tree, [parent])
    master_ref.edit(commit.sha)
示例#25
0
def create_pull_request(repository, issue):
    print("Creating pull request on:", repository.name)
    repo.create_git_ref(
        ref=branch,
        sha=repo.get_git_refs()[0].object.sha
    )
    existing = repo.get_git_tree(repo.get_commits()[0].sha, recursive=True)
    new_tree = []
    for item in existing.tree:
        new_tree.append(InputGitTreeElement(path=item.path, mode=item.mode, type=item.type, sha=item.sha))
    new_tree.append(InputGitTreeElement(".timestamp", "100644", "blob", content=test_id))
    tree = repo.create_git_tree(new_tree)

    new_commit = repo.create_git_commit(
        message=title,
        tree=tree,
        parents=[repo.get_commits()[0].commit]
    )
    branch_ref = repo.get_git_ref("heads/%s" % time_str)
    branch_ref.edit(new_commit.sha)
    pull = repo.create_pull(title, "Supports %s" % issue.html_url, "master", branch)
    print("Created pull request successfully:", pull.number)
    return pull
示例#26
0
def addxml(request):
    #generate xml file
    xmlstr = '''<book>
                    <bookid>{bookid}</bookid>
                    <title>{title}</title>
                    <author>{author}</author>
                    <image>{image}</image>
                    <link>{link}</link>
                    <epub>{epub}</epub>
                    <pdf>{pdf}</pdf>
                    <category>{category}</category>
                    <date>{date}</date>
                </book>'''.format(bookid=request.POST['bookid'],
                                  title=request.POST['title'],
                                  author=request.POST['author'],
                                  image=request.POST['image'],
                                  link=request.POST['link'],
                                  epub=request.POST['epub'],
                                  pdf=request.POST['pdf'],
                                  category=request.POST['category'],
                                  date=request.POST['date'])

    #change the token here
    token = '2b078f735e2a91f37f244d244751ac5499d54411'
    g = Github(token)
    #change the repository name
    repo = g.get_user().get_repo('xmlpush')

    with open('booksdb.xml', 'a+') as f:
        f.write(xmlstr + '\n')

    #change xml file name
    file_list = ['booksdb.xml']
    commit_message = request.POST['commitmsg']
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)

    element_list = list()
    for entry in file_list:
        with open(entry, 'r') as input_file:
            data = input_file.read()
        element = InputGitTreeElement(entry, '100644', 'blob', data)
        element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)

    return HttpResponse("Pushed to git repo")
示例#27
0
def commit_to_git():
    commit_lock.acquire()
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    with open(data_path) as input_file:
        data = input_file.read()
    element = InputGitTreeElement('bot.properties', '100644', 'blob', data)
    element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)
    commit_lock.release()
示例#28
0
 def _create_input_tree_multi(filenames,repo,
                              base_tree=GithubObject.NotSet,
                              mode="100644"):
     """ generate a GitTreeElement for a file(s) (a Git commit is 1 or more GitTreeElements)
     :param filenames: list of full path of the file
     :repo : Repository
     :rtype: GitTreeElement
     """
     tree_input = []
     
     for filename in filenames:
         file_str = os_file_to_string(filename)
         tree_input.append(InputGitTreeElement(filename,mode,
                                                "blob",file_str))
     return repo.create_git_tree(tree_input,
                                 base_tree=base_tree)
示例#29
0
 def push_to_github(self, access_token):
     message = "Commit from Naming Matters"
     g = Github(access_token)
     repo = g.get_repo(self.name)
     ref = repo.get_git_ref(f"heads/{self.branch}")
     tree = repo.get_git_tree(ref.object.sha, recursive=True)
     commit = repo.get_git_commit(ref.object.sha)
     inputs = [
         InputGitTreeElement(path, "100644", "blob", content=content)
         for (path, content) in self.files().items()
     ]
     new_tree = repo.create_git_tree(inputs, base_tree=tree)
     new_commit = repo.create_git_commit(message=message,
                                         parents=[commit],
                                         tree=new_tree)
     ref.edit(new_commit.sha)
     return new_commit.sha
示例#30
0
def git_commit():
    commit_message = 'News link update'
    master_ref = repo.get_git_ref('heads/master')
    master_sha = master_ref.object.sha
    base_tree = repo.get_git_tree(master_sha)
    element_list = list()
    for i, entry in enumerate(file_list):
        with open(entry) as input_file:
            data = input_file.read()
        if entry.endswith('.png'):
            data = base64.b64encode(data)
        element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
        element_list.append(element)
    tree = repo.create_git_tree(element_list, base_tree)
    parent = repo.get_git_commit(master_sha)
    commit = repo.create_git_commit(commit_message, tree, [parent])
    master_ref.edit(commit.sha)
示例#31
0
def github_push(user, commit_message, repo_name, project):
    g = Github(user.github.token, client_id=settings.GITHUB_CLIENT_ID, client_secret=settings.GITHUB_CLIENT_SECRET)
    repo = g.get_repo(repo_name)
    try:
        branch = repo.get_branch(project.github_branch or repo.master_branch)
    except GithubException:
        raise Exception("Unable to get branch.")
    commit = repo.get_git_commit(branch.commit.sha)
    tree = repo.get_git_tree(commit.tree.sha, recursive=True)

    paths = [x.path for x in tree.tree]

    next_tree = {x.path: InputGitTreeElement(path=x.path, mode=x.mode, type=x.type, sha=x.sha) for x in tree.tree}

    try:
        root = find_project_root(paths)
    except:
        root = ''

    src_root = root + 'src/'
    project_sources = project.source_files.all()
    has_changed = False
    for source in project_sources:
        repo_path = src_root + source.file_name
        if repo_path not in next_tree:
            has_changed = True
            next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob',
                                                       content=source.get_contents())
            print "New file: %s" % repo_path
        else:
            sha = next_tree[repo_path]._InputGitTreeElement__sha
            our_content = source.get_contents()
            expected_sha = git_sha(our_content)
            if expected_sha != sha:
                print "Updated file: %s" % repo_path
                next_tree[repo_path]._InputGitTreeElement__sha = NotSet
                next_tree[repo_path]._InputGitTreeElement__content = our_content
                has_changed = True

    expected_source_files = [src_root + x.file_name for x in project_sources]
    for path in next_tree.keys():
        if not path.startswith(src_root):
            continue
        if path not in expected_source_files:
            del next_tree[path]
            print "Deleted file: %s" % path
            has_changed = True

    # Now try handling resource files.

    resources = project.resources.all()

    resource_root = root + 'resources/'

    for res in resources:
        for variant in res.variants.all():
            repo_path = resource_root + variant.path
            if repo_path in next_tree:
                content = variant.get_contents()
                if git_sha(content) != next_tree[repo_path]._InputGitTreeElement__sha:
                    print "Changed resource: %s" % repo_path
                    has_changed = True
                    blob = repo.create_git_blob(base64.b64encode(content), 'base64')
                    print "Created blob %s" % blob.sha
                    next_tree[repo_path]._InputGitTreeElement__sha = blob.sha
            else:
                print "New resource: %s" % repo_path
                blob = repo.create_git_blob(base64.b64encode(variant.get_contents()), 'base64')
                print "Created blob %s" % blob.sha
                next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob', sha=blob.sha)

    remote_manifest_path = root + 'appinfo.json'
    remote_wscript_path = root + 'wscript'

    remote_manifest_sha = next_tree[remote_manifest_path]._InputGitTreeElement__sha if remote_manifest_path in next_tree else None
    if remote_manifest_sha is not None:
        their_manifest_dict = json.loads(git_blob(repo, remote_manifest_sha))
        their_res_dict = their_manifest_dict['resources']
    else:
        their_manifest_dict = {}
        their_res_dict = {'media': []}

    our_manifest_dict = generate_manifest_dict(project, resources)
    our_res_dict = our_manifest_dict['resources']

    if our_res_dict != their_res_dict:
        print "Resources mismatch."
        has_changed = True
        # Try removing things that we've deleted, if any
        to_remove = set(x['file'] for x in their_res_dict['media']) - set(x['file'] for x in our_res_dict['media'])
        for path in to_remove:
            repo_path = resource_root + path
            if repo_path in next_tree:
                print "Deleted resource: %s" % repo_path
                del next_tree[repo_path]

    # This one is separate because there's more than just the resource map changing.
    if their_manifest_dict != our_manifest_dict:
        if remote_manifest_path in next_tree:
            next_tree[remote_manifest_path]._InputGitTreeElement__sha = NotSet
            next_tree[remote_manifest_path]._InputGitTreeElement__content = generate_manifest(project, resources)
        else:
            next_tree[remote_manifest_path] = InputGitTreeElement(path=remote_manifest_path, mode='100644', type='blob',
                                                                  content=generate_manifest(project, resources))

    if project.project_type == 'native' and remote_wscript_path not in next_tree:
        next_tree[remote_wscript_path] = InputGitTreeElement(path=remote_wscript_path, mode='100644', type='blob',
                                                             content=generate_wscript_file(project, True))
        has_changed = True

    # Commit the new tree.
    if has_changed:
        print "Has changed; committing"
        # GitHub seems to choke if we pass the raw directory nodes off to it,
        # so we delete those.
        for x in next_tree.keys():
            if next_tree[x]._InputGitTreeElement__mode == '040000':
                del next_tree[x]
                print "removing subtree node %s" % x

        print [x._InputGitTreeElement__mode for x in next_tree.values()]
示例#32
0
def github_push(user, commit_message, repo_name, project):
    g = Github(user.github.token, client_id=settings.GITHUB_CLIENT_ID, client_secret=settings.GITHUB_CLIENT_SECRET)
    repo = g.get_repo(repo_name)
    try:
        branch = repo.get_branch(project.github_branch or repo.master_branch)
    except GithubException:
        raise Exception("Unable to get branch.")
    commit = repo.get_git_commit(branch.commit.sha)
    tree = repo.get_git_tree(commit.tree.sha, recursive=True)

    paths = [x.path for x in tree.tree]

    next_tree = {x.path: InputGitTreeElement(path=x.path, mode=x.mode, type=x.type, sha=x.sha) for x in tree.tree}

    try:
        remote_version, root = find_project_root(paths)
    except:
        remote_version, root = project.sdk_version, ''

    src_root = root + 'src/'
    project_sources = project.source_files.all()
    has_changed = False
    for source in project_sources:
        repo_path = src_root + source.file_name
        if repo_path not in next_tree:
            has_changed = True
            next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob',
                                                       content=source.get_contents())
            print "New file: %s" % repo_path
        else:
            sha = next_tree[repo_path]._InputGitTreeElement__sha
            our_content = source.get_contents()
            expected_sha = git_sha(our_content)
            if expected_sha != sha:
                print "Updated file: %s" % repo_path
                next_tree[repo_path]._InputGitTreeElement__sha = NotSet
                next_tree[repo_path]._InputGitTreeElement__content = our_content
                has_changed = True

    expected_source_files = [src_root + x.file_name for x in project_sources]
    for path in next_tree.keys():
        if not path.startswith(src_root):
            continue
        if path not in expected_source_files:
            del next_tree[path]
            print "Deleted file: %s" % path
            has_changed = True

    # Now try handling resource files.

    resources = project.resources.all()

    old_resource_root = root + ("resources/src/" if remote_version == '1' else 'resources/')
    new_resource_root = root + ("resources/src/" if project.sdk_version == '1' else 'resources/')

    # Migrate all the resources so we can subsequently ignore the issue.
    if old_resource_root != new_resource_root:
        print "moving resources"
        new_next_tree = next_tree.copy()
        for path in next_tree:
            if path.startswith(old_resource_root) and not path.endswith('resource_map.json'):
                new_path = new_resource_root + path[len(old_resource_root):]
                print "moving %s to %s" % (path, new_path)
                next_tree[path]._InputGitTreeElement__path = new_path
                new_next_tree[new_path] = next_tree[path]
                del new_next_tree[path]
        next_tree = new_next_tree

    for res in resources:
        repo_path = new_resource_root + res.path
        if repo_path in next_tree:
            content = res.get_contents()
            if git_sha(content) != next_tree[repo_path]._InputGitTreeElement__sha:
                print "Changed resource: %s" % repo_path
                has_changed = True
                blob = repo.create_git_blob(base64.b64encode(content), 'base64')
                print "Created blob %s" % blob.sha
                next_tree[repo_path]._InputGitTreeElement__sha = blob.sha
        else:
            print "New resource: %s" % repo_path
            blob = repo.create_git_blob(base64.b64encode(res.get_contents()), 'base64')
            print "Created blob %s" % blob.sha
            next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob', sha=blob.sha)

    # Both of these are used regardless of version
    remote_map_path = root + 'resources/src/resource_map.json'
    remote_manifest_path = root + 'appinfo.json'
    remote_wscript_path = root + 'wscript'

    if remote_version == '1':
        remote_map_sha = next_tree[remote_map_path]._InputGitTreeElement__sha if remote_map_path in next_tree else None
        if remote_map_sha is not None:
            their_res_dict = json.loads(git_blob(repo, remote_map_sha))
        else:
            their_res_dict = {'friendlyVersion': 'VERSION', 'versionDefName': '', 'media': []}
        their_manifest_dict = {}
    else:
        remote_manifest_sha = next_tree[remote_manifest_path]._InputGitTreeElement__sha if remote_map_path in next_tree else None
        if remote_manifest_sha is not None:
            their_manifest_dict = json.loads(git_blob(repo, remote_manifest_sha))
            their_res_dict = their_manifest_dict['resources']
        else:
            their_manifest_dict = {}
            their_res_dict = {'media': []}

    if project.sdk_version == '1':
        our_res_dict = generate_resource_dict(project, resources)
    else:
        our_manifest_dict = generate_v2_manifest_dict(project, resources)
        our_res_dict = our_manifest_dict['resources']

    if our_res_dict != their_res_dict:
        print "Resources mismatch."
        has_changed = True
        # Try removing things that we've deleted, if any
        to_remove = set(x['file'] for x in their_res_dict['media']) - set(x['file'] for x in our_res_dict['media'])
        for path in to_remove:
            repo_path = new_resource_root + path
            if repo_path in next_tree:
                print "Deleted resource: %s" % repo_path
                del next_tree[repo_path]

        # Update the stored resource map, if applicable.
        if project.sdk_version == '1':
            if remote_map_path in next_tree:
                next_tree[remote_map_path]._InputGitTreeElement__sha = NotSet
                next_tree[remote_map_path]._InputGitTreeElement__content = dict_to_pretty_json(our_res_dict)
            else:
                next_tree[remote_map_path] = InputGitTreeElement(path=remote_map_path, mode='100644', type='blob',
                                                                 content=dict_to_pretty_json(our_res_dict))
            # Delete the v2 manifest, if one exists
            if remote_manifest_path in next_tree:
                del next_tree[remote_manifest_path]
    # This one is separate because there's more than just the resource map changing.
    if project.sdk_version == '2' and their_manifest_dict != our_manifest_dict:
        if remote_manifest_path in next_tree:
            next_tree[remote_manifest_path]._InputGitTreeElement__sha = NotSet
            next_tree[remote_manifest_path]._InputGitTreeElement__content = generate_v2_manifest(project, resources)
        else:
            next_tree[remote_manifest_path] = InputGitTreeElement(path=remote_manifest_path, mode='100644', type='blob',
                                                                  content=generate_v2_manifest(project, resources))
        # Delete the v1 manifest, if one exists
        if remote_map_path in next_tree:
            del next_tree[remote_map_path]

    if project.sdk_version == '2':
        if remote_wscript_path not in next_tree:
            next_tree[remote_wscript_path] = InputGitTreeElement(path=remote_wscript_path, mode='100644', type='blob',
                                                                 content=generate_wscript_file(project, True))
            has_changed = True
    else:
        del next_tree[remote_wscript_path]

    # Commit the new tree.
    if has_changed:
        print "Has changed; committing"
        # GitHub seems to choke if we pass the raw directory nodes off to it,
        # so we delete those.
        for x in next_tree.keys():
            if next_tree[x]._InputGitTreeElement__mode == '040000':
                del next_tree[x]
                print "removing subtree node %s" % x

        print [x._InputGitTreeElement__mode for x in next_tree.values()]
示例#33
0
def github_push(user, commit_message, repo_name, project):
    g = Github(user.github.token, client_id=settings.GITHUB_CLIENT_ID, client_secret=settings.GITHUB_CLIENT_SECRET)
    repo = g.get_repo(repo_name)
    try:
        branch = repo.get_branch(project.github_branch or repo.master_branch)
    except GithubException:
        raise Exception("Unable to get branch.")
    commit = repo.get_git_commit(branch.commit.sha)
    tree = repo.get_git_tree(commit.tree.sha, recursive=True)

    paths = [x.path for x in tree.tree]

    next_tree = {x.path: InputGitTreeElement(path=x.path, mode=x.mode, type=x.type, sha=x.sha) for x in tree.tree}

    try:
        root = find_project_root(paths)
    except:
        root = ''
    expected_paths = set()

    def update_expected_paths(new_path):
        # This adds the path *and* its parent directories to the list of expected paths.
        # The parent directories are already keys in next_tree, so if they aren't present in expected_paths
        # then, when iterating over next_tree to see which files have been deleted, we would have to treat
        # directories as special cases.
        split_path = new_path.split('/')
        expected_paths.update('/'.join(split_path[:p]) for p in range(2, len(split_path) + 1))

    src_root = root + 'src/'
    worker_src_root = root + 'worker_src/'
    project_sources = project.source_files.all()
    has_changed = False
    for source in project_sources:
        repo_path = src_root + source.file_name
        if project.project_type == 'native':
            if source.target == 'worker':
                repo_path = worker_src_root + source.file_name
            elif project.app_modern_multi_js and source.file_name.endswith('.js'):
                repo_path = src_root + 'js/' + source.file_name

        update_expected_paths(repo_path)
        if repo_path not in next_tree:
            has_changed = True
            next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob',
                                                       content=source.get_contents())
            print "New file: %s" % repo_path
        else:
            sha = next_tree[repo_path]._InputGitTreeElement__sha
            our_content = source.get_contents()
            expected_sha = git_sha(our_content)
            if expected_sha != sha:
                print "Updated file: %s" % repo_path
                next_tree[repo_path]._InputGitTreeElement__sha = NotSet
                next_tree[repo_path]._InputGitTreeElement__content = our_content
                has_changed = True

    # Now try handling resource files.
    resources = project.resources.all()
    resource_root = root + 'resources/'
    for res in resources:
        for variant in res.variants.all():
            repo_path = resource_root + variant.path
            update_expected_paths(repo_path)
            if repo_path in next_tree:
                content = variant.get_contents()
                if git_sha(content) != next_tree[repo_path]._InputGitTreeElement__sha:
                    print "Changed resource: %s" % repo_path
                    has_changed = True
                    blob = repo.create_git_blob(base64.b64encode(content), 'base64')
                    print "Created blob %s" % blob.sha
                    next_tree[repo_path]._InputGitTreeElement__sha = blob.sha
            else:
                print "New resource: %s" % repo_path
                has_changed = True
                blob = repo.create_git_blob(base64.b64encode(variant.get_contents()), 'base64')
                print "Created blob %s" % blob.sha
                next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob', sha=blob.sha)

    # Manage deleted files
    for path in next_tree.keys():
        if not (any(path.startswith(root) for root in (src_root, resource_root, worker_src_root))):
            continue
        if path not in expected_paths:
            del next_tree[path]
            print "Deleted file: %s" % path
            has_changed = True

    # Compare the resource dicts
    remote_manifest_path = root + 'appinfo.json'
    remote_wscript_path = root + 'wscript'

    remote_manifest_sha = next_tree[remote_manifest_path]._InputGitTreeElement__sha if remote_manifest_path in next_tree else None
    if remote_manifest_sha is not None:
        their_manifest_dict = json.loads(git_blob(repo, remote_manifest_sha))
        their_res_dict = their_manifest_dict['resources']
    else:
        their_manifest_dict = {}
        their_res_dict = {'media': []}

    our_manifest_dict = generate_manifest_dict(project, resources)
    our_res_dict = our_manifest_dict['resources']

    if our_res_dict != their_res_dict:
        print "Resources mismatch."
        has_changed = True
        # Try removing things that we've deleted, if any
        to_remove = set(x['file'] for x in their_res_dict['media']) - set(x['file'] for x in our_res_dict['media'])
        for path in to_remove:
            repo_path = resource_root + path
            if repo_path in next_tree:
                print "Deleted resource: %s" % repo_path
                del next_tree[repo_path]

    # This one is separate because there's more than just the resource map changing.
    if their_manifest_dict != our_manifest_dict:
        has_changed = True
        if remote_manifest_path in next_tree:
            next_tree[remote_manifest_path]._InputGitTreeElement__sha = NotSet
            next_tree[remote_manifest_path]._InputGitTreeElement__content = generate_manifest(project, resources)
        else:
            next_tree[remote_manifest_path] = InputGitTreeElement(path=remote_manifest_path, mode='100644', type='blob',
                                                                  content=generate_manifest(project, resources))

    if project.project_type == 'native' and remote_wscript_path not in next_tree:
        next_tree[remote_wscript_path] = InputGitTreeElement(path=remote_wscript_path, mode='100644', type='blob',
                                                             content=generate_wscript_file(project, True))
        has_changed = True

    # Commit the new tree.
    if has_changed:
        print "Has changed; committing"
        # GitHub seems to choke if we pass the raw directory nodes off to it,
        # so we delete those.
        for x in next_tree.keys():
            if next_tree[x]._InputGitTreeElement__mode == '040000':
                del next_tree[x]
                print "removing subtree node %s" % x

        print [x._InputGitTreeElement__mode for x in next_tree.values()]
示例#34
0
def github_push(user, commit_message, repo_name, project):
    g = Github(user.github.token, client_id=settings.GITHUB_CLIENT_ID, client_secret=settings.GITHUB_CLIENT_SECRET)
    repo = g.get_repo(repo_name)
    try:
        branch = repo.get_branch(project.github_branch or repo.master_branch)
    except GithubException:
        raise Exception("Unable to get branch.")
    commit = repo.get_git_commit(branch.commit.sha)
    tree = repo.get_git_tree(commit.tree.sha, recursive=True)

    next_tree = {x.path: InputGitTreeElement(path=x.path, mode=x.mode, type=x.type, sha=x.sha) for x in tree.tree}

    try:
        root, manifest_item = find_project_root_and_manifest([GitProjectItem(repo, x) for x in tree.tree])
    except InvalidProjectArchiveException:
        root = ''
        manifest_item = None

    expected_paths = set()

    def update_expected_paths(new_path):
        # This adds the path *and* its parent directories to the list of expected paths.
        # The parent directories are already keys in next_tree, so if they aren't present in expected_paths
        # then, when iterating over next_tree to see which files have been deleted, we would have to treat
        # directories as special cases.
        split_path = new_path.split('/')
        expected_paths.update('/'.join(split_path[:p]) for p in range(2, len(split_path) + 1))

    src_root = root + 'src/'
    worker_src_root = root + 'worker_src/'
    project_sources = project.source_files.all()
    has_changed = False
    for source in project_sources:
        repo_path = src_root + source.file_name
        if project.project_type == 'native':
            if source.target == 'worker':
                repo_path = worker_src_root + source.file_name
            elif project.app_modern_multi_js and source.file_name.endswith('.js'):
                repo_path = src_root + 'js/' + source.file_name

        update_expected_paths(repo_path)
        if repo_path not in next_tree:
            has_changed = True
            next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob',
                                                       content=source.get_contents())
            logger.debug("New file: %s", repo_path)
        else:
            sha = next_tree[repo_path]._InputGitTreeElement__sha
            our_content = source.get_contents()
            expected_sha = git_sha(our_content)
            if expected_sha != sha:
                logger.debug("Updated file: %s", repo_path)
                next_tree[repo_path]._InputGitTreeElement__sha = NotSet
                next_tree[repo_path]._InputGitTreeElement__content = our_content
                has_changed = True

    # Now try handling resource files.
    resources = project.resources.all()
    resource_root = root + 'resources/'
    for res in resources:
        for variant in res.variants.all():
            repo_path = resource_root + variant.path
            update_expected_paths(repo_path)
            if repo_path in next_tree:
                content = variant.get_contents()
                if git_sha(content) != next_tree[repo_path]._InputGitTreeElement__sha:
                    logger.debug("Changed resource: %s", repo_path)
                    has_changed = True
                    blob = repo.create_git_blob(base64.b64encode(content), 'base64')
                    logger.debug("Created blob %s", blob.sha)
                    next_tree[repo_path]._InputGitTreeElement__sha = blob.sha
            else:
                logger.debug("New resource: %s", repo_path)
                has_changed = True
                blob = repo.create_git_blob(base64.b64encode(variant.get_contents()), 'base64')
                logger.debug("Created blob %s", blob.sha)
                next_tree[repo_path] = InputGitTreeElement(path=repo_path, mode='100644', type='blob', sha=blob.sha)

    # Manage deleted files
    for path in next_tree.keys():
        if not (any(path.startswith(root) for root in (src_root, resource_root, worker_src_root))):
            continue
        if path not in expected_paths:
            del next_tree[path]
            logger.debug("Deleted file: %s", path)
            has_changed = True

    # Compare the resource dicts
    remote_manifest_path = root + manifest_name_for_project(project)
    remote_wscript_path = root + 'wscript'

    if manifest_item:
        their_manifest_dict = json.loads(manifest_item.read())
        their_res_dict = their_manifest_dict.get('resources', their_manifest_dict.get('pebble', their_manifest_dict).get('resources', {'media': []}))
        # If the manifest needs a new path (e.g. it is now package.json), delete the old one
        if manifest_item.path != remote_manifest_path:
            del next_tree[manifest_item.path]
    else:
        their_manifest_dict = {}
        their_res_dict = {'media': []}

    our_manifest_dict = generate_manifest_dict(project, resources)
    our_res_dict = our_manifest_dict.get('resources', our_manifest_dict.get('pebble', our_manifest_dict).get('resources', {'media': []}))

    if our_res_dict != their_res_dict:
        logger.debug("Resources mismatch.")
        has_changed = True
        # Try removing things that we've deleted, if any
        to_remove = set(x['file'] for x in their_res_dict['media']) - set(x['file'] for x in our_res_dict['media'])
        for path in to_remove:
            repo_path = resource_root + path
            if repo_path in next_tree:
                logger.debug("Deleted resource: %s", repo_path)
                del next_tree[repo_path]

    # This one is separate because there's more than just the resource map changing.
    if their_manifest_dict != our_manifest_dict:
        has_changed = True
        if remote_manifest_path in next_tree:
            next_tree[remote_manifest_path]._InputGitTreeElement__sha = NotSet
            next_tree[remote_manifest_path]._InputGitTreeElement__content = generate_manifest(project, resources)
        else:
            next_tree[remote_manifest_path] = InputGitTreeElement(path=remote_manifest_path, mode='100644', type='blob',
                                                                  content=generate_manifest(project, resources))

    if project.project_type == 'native' and remote_wscript_path not in next_tree:
        next_tree[remote_wscript_path] = InputGitTreeElement(path=remote_wscript_path, mode='100644', type='blob',
                                                             content=generate_wscript_file(project, True))
        has_changed = True

    # Commit the new tree.
    if has_changed:
        logger.debug("Has changed; committing")
        # GitHub seems to choke if we pass the raw directory nodes off to it,
        # so we delete those.
        for x in next_tree.keys():
            if next_tree[x]._InputGitTreeElement__mode == '040000':
                del next_tree[x]
                logger.debug("removing subtree node %s", x)

        logger.debug([x._InputGitTreeElement__mode for x in next_tree.values()])
        git_tree = repo.create_git_tree(next_tree.values())
        logger.debug("Created tree %s", git_tree.sha)
        git_commit = repo.create_git_commit(commit_message, git_tree, [commit])
        logger.debug("Created commit %s", git_commit.sha)
        git_ref = repo.get_git_ref('heads/%s' % (project.github_branch or repo.master_branch))
        git_ref.edit(git_commit.sha)
        logger.debug("Updated ref %s", git_ref.ref)
        project.github_last_commit = git_commit.sha
        project.github_last_sync = now()
        project.save()
        return True

    send_td_event('cloudpebble_github_push', data={
        'data': {
            'repo': project.github_repo
        }
    }, user=user)

    return False