13

How to Perform Git Operations with PHP

 3 years ago
source link: https://www.devdungeon.com/content/how-perform-git-operations-php
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Git operations can be performed programmatically with PHP using the libgit2 library. Here are some common operations.

Cloning a Repository

$repo = git_clone("https://github.com/nanodano/reference", "/tmp/reference");

Opening a repository

$repo = git_repository_open("/tmp/reference");

Git Blame

This will blame the README.md file from HEAD

$options = git_blame_options_new();
$blame = git_blame_file($repo, "README.md", $options);
$obj = git_revparse_single($repo, "HEAD:README.md");
$id = git_object_id($obj);
$blob = git_blob_lookup($repo, $id);
$raw = git_blob_rawcontent($blob);
$i = 0;
$lines = explode("\n", $raw);

foreach ($lines as $data) {
    $hunk = git_blame_get_hunk_byline($blame, $i+1);
    if (!$hunk) {
        continue;
    }
    $sig = sprintf("%s <%s>", $hunk['final_signature']['name'], $hunk['final_signature']['email']);
    printf("%s ( %-30s, %4d) %s\n", substr($hunk['final_commit_id'], 10),
        $sig,
        $i+1,
        $data
    );
    $i++;
}

Git Diff

$tree = git_tree_lookup($repo, "e14ccb8e18d632d78ce2f0aeb06597a03f42b237");
$diff = git_diff_tree_to_workdir($repo, $tree, git_diff_options_init());
$p = array();
git_diff_print($diff, GIT_DIFF_FORMAT_PATCH, function($diff_delta, $diff_hunk, $diff_line, $payload){
    if ($diff_line['origin'] == "-" || $diff_line['origin'] == "+") {
        echo $diff_line['origin'];
    }
    echo $diff_line['content'];
}, $p);

Git Patch

$tree = git_tree_lookup($repo, "e14ccb8e18d632d78ce2f0aeb06597a03f42b237");
$diff = git_diff_tree_to_workdir($repo, $tree, git_diff_options_init());
$payload = array();
$patch = git_patch_from_diff($diff, 1);
git_patch_print($patch, function($diff_delta, $diff_hunk, $diff_line, $payload){
    if ($diff_line['origin'] == "-" || $diff_line['origin'] == "+") {
        echo $diff_line['origin'];
    }
    echo $diff_line['content'];
}, $payload);

Git Push

$payload = array();
$repo    = git_repository_open(".");
$remote  = git_remote_load($repo, "origin");
$remote_callbacks = [
    "credentials" => function($url, $username_from_url, $allowed_types, &$payload) {
        // Build with LibSSH2 to use ssh protocol.
        if ($allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) {
            return git_cred_userpass_plaintext_new("nanodano", getenv("GITHUB_TOKEN"));
        } else {
            error_log("not supported allowed types");
        }
}];

git_remote_set_callbacks($remote, $remote_callbacks);

if (git_remote_connect($remote, GIT_DIRECTION_PUSH)) {
    $push = git_push_new($remote);
    git_push_add_refspec($push, "refs/heads/master:refs/heads/master");
    git_push_finish($push);
    git_push_unpack_ok($push);
    git_push_status_foreach($push, function($ref, $name, &$payload){
        var_dump($ref, $name, $payload);
    }, $payload);
    git_push_update_tips($push);
    git_remote_disconnect($remote);
}

Reference Lookup

$ref = git_reference_dwim($repo, "HEAD");
$obj =  git_reference_peel($ref, GIT_OBJ_ANY);
echo git_object_id($obj);

Reference Log

$reflog = git_reflog_read($repo, "HEAD");

$count = git_reflog_entrycount($reflog);

for ($i = 0; $i < $count; $i++) {
    $entry = git_reflog_entry_byindex($reflog, $i);
    var_dump(git_reflog_entry_committer($entry));
}

Git Status

$list = git_status_list_new($repo, array());

$payload = array();

printf("# Changes to be committed:\n");
printf("#   (use "git reset HEAD <file>..." to unstage)\n");
printf("#\n");

$cnt = git_status_list_entrycount($list);

for ($i = 0; $i < $cnt; $i++) {
    $entry = git_status_byindex($list, $i);
    $flags = $entry['status'];
    $stat = getStat($flags);
    if (is_array($entry['head_to_index'])) {
        printf("# %15s %s\n", $stat, $entry['head_to_index']['new_file']['path']);
    }
}

printf("#\n");
printf("# Changes not staged for commit:\n");
printf("#   (use "git add <file>..." to update what will be committed)\n");
printf("#   (use "git checkout -- <file>..." to discard changes in working directory)\n");
printf("#\n");

for ($i = 0; $i < $cnt; $i++) {
    $entry = git_status_byindex($list, $i);
    $flags = $entry['status'];
    $stat = getStat($flags);
    if (is_array($entry['index_to_workdir'])) {
        printf("# %15s %s\n", $stat, $entry['index_to_workdir']['new_file']['path']);
    }
}

printf("#\n");

function getStat($flags)
{
    $stat = "";
    if ($flags & GIT_STATUS_IGNORED) {
        return;
    }
    if ($flags == GIT_STATUS_CURRENT) {
        return;
    }
    if ($flags & GIT_STATUS_INDEX_NEW){
        $stat = "new file:";
    }
    if ($flags & GIT_STATUS_WT_NEW) {
        $stat = "untracked:";
    }
    if ($flags & GIT_STATUS_INDEX_MODIFIED ||$flags & GIT_STATUS_WT_MODIFIED) {
        $stat = "modified:";
    }
    if ($flags & GIT_STATUS_INDEX_DELETED || $flags & GIT_STATUS_WT_DELETED) {
        $stat = "deleted:";
    }
    if ($flags & GIT_STATUS_INDEX_RENAMED || $flags & GIT_STATUS_WT_RENAMED) {
        $stat = "renamed:";
    }
    if ($flags & GIT_STATUS_INDEX_TYPECHANGE || $flags & GIT_STATUS_WT_TYPECHANGE) {
        $stat = "typechange:";
    }
    return $stat;
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK