Wanchai / FTPbucket

FTPbucket is a PHP script that enables you to sync your BitBucket or GitHub repository with any web-server
102 stars 22 forks source link

Not all commits are retrieved #15

Closed d2roth closed 5 years ago

d2roth commented 7 years ago

According to the documentation the commits in $this->payload['push']['changes'] will not be complete.

commits: An array containing up to 5 of the most recent commits pushed to the reference. The array for a push with more than 5 commits is truncated, which is indicated by the truncated property.

To remedy that issue there is the commits endpoint and you can find all of the commits present between two commits. The structure is as follows: https://bitbucket.org/api/2.0/repositories/2.0/repositories/{username}/{repo_slug}/commits/{revision}

I made the following function and call it with:

$change_commits = $this->fetch_commits($change['old']['target']['hash'], $change['new']['target']['hash']);
function fetch_commits($old_hash, $new_hash){
    $url = 'https://bitbucket.org/api/2.0/repositories/'.$this->data->ftp['full_name'].'/commits/';

    // For debugging you can set pagelen down so it retrieves less commits each time
    // $args = ['pagelen' => 10];
    $args = [];

    // If there is no old_hash provided or the exclude parameter is not present commits from the beginning of time will be retrieved
    if(!empty($old_hash) && $old_hash != "null"){
        $args['exclude'] = $old_hash;
    }

    // If there is no new_hash provided or the include parameter is not present commits from the end of time will be retrieved
    if(!empty($new_hash) && $new_hash != 'null'){
        $args['include'] = $new_hash;
    }

    $url = $url . '?' . http_build_query($args);

    $has_more = true;
    $all_results = [];

    // Loop through until there are not more pages of results
    do{
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_USERPWD, $this->data->auth['username'] . ':' . $this->data->auth['password']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
        $data = curl_exec($ch);
        /**
         * Check for HTTP return status instead of the data that is returned from
         * CURL. This ensures that even an empty file will be transfered properly.
         */
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if ($http_code != 200) {
            $this->error('Cant\'t get lists of commits! HTTP_CODE: ' . $http_code . ' cURL error: ' . curl_error($ch));
        } else {
            $arr = json_decode($data, true);
            if (isset($arr["error"]))
                $this->error("cURL error: " . print_r($arr, true));
        }
        $result = json_decode($data, true);

        $has_more = isset($result['next']) && !empty($result['next']);
        if($has_more){
            $url = $result['next'];
        }
        // Make sure decoding worked
        if(!is_null($result) && is_array($result['values'])){
            $all_results = array_merge($all_results, $result['values']);
        }
    }while($has_more);

    return $all_results;
}

There might be a more elegant way to grab all the files but this does the trick for now to retrieve all of the commits between two hashes. What I haven't checked is what happens when 2 commits are in different branches or other variations. Also while I was testing this I found if you create a new branch the old hash will be null so all of the commit's in the history before that branch will be retrieved. This means it can take a while for a branch to be pushed for the first time.

If you want I can make a pull request with this improvement.

Wanchai commented 6 years ago

Sorry for the late response but it would be great if you could do a pull request indeed.

Thanks!

d2roth commented 6 years ago

Okay. I will look into that. It might be a couple of days before I can get to it but anything I should know when making it?

Wanchai commented 6 years ago

Nothing special. I'll make some corrections if I see some possible improvements.

Cheers.