Subversion Repositories oidplus

Rev

Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * Copyright (C) 2008, 2009 Patrik Fimml
  5.  * Copyright (c) 2023 Daniel Marschall
  6.  *
  7.  * This file is part of glip.
  8.  *
  9.  * glip is free software: you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation, either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  
  14.  * glip is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with glip.  If not, see <http://www.gnu.org/licenses/>.
  21.  */
  22.  
  23. namespace ViaThinkSoft\Glip;
  24.  
  25. class GitCommit extends GitObject
  26. {
  27.         /**
  28.          * @brief (string) The tree referenced by this commit, as binary sha1
  29.          * string.
  30.          */
  31.         public $tree;
  32.  
  33.         /**
  34.          * @brief (array of string) Parent commits of this commit, as binary sha1
  35.          * strings.
  36.          */
  37.         public $parents;
  38.  
  39.         /**
  40.          * @brief (GitCommitStamp) The author of this commit.
  41.          */
  42.         public $author;
  43.  
  44.         /**
  45.          * @brief (GitCommitStamp) The committer of this commit.
  46.          */
  47.         public $committer;
  48.  
  49.         /**
  50.          * @brief (string) Commit summary, i.e. the first line of the commit message.
  51.          */
  52.         public $summary;
  53.  
  54.         /**
  55.          * @brief (string) Everything after the first line of the commit message.
  56.          */
  57.         public $detail;
  58.  
  59.         public $history;
  60.  
  61.         public function __construct($repo) {
  62.                 parent::__construct($repo, Git::OBJ_COMMIT);
  63.         }
  64.  
  65.         public function _unserialize($data) {
  66.                 $lines = explode("\n", $data);
  67.                 unset($data);
  68.                 $meta = array('parent' => array());
  69.                 while (($line = array_shift($lines)) != '') {
  70.                         $parts = explode(' ', $line, 2);
  71.                         if (!isset($meta[$parts[0]]))
  72.                                 $meta[$parts[0]] = array($parts[1]);
  73.                         else
  74.                                 $meta[$parts[0]][] = $parts[1];
  75.                 }
  76.  
  77.                 $this->tree = pack('H40', $meta['tree'][0]);
  78.                 $this->parents = array_map(function ($hex) {
  79.                         return pack('H40', $hex);
  80.                 }, $meta['parent']);
  81.                 $this->author = new GitCommitStamp;
  82.                 $this->author->unserialize($meta['author'][0]);
  83.                 $this->committer = new GitCommitStamp;
  84.                 $this->committer->unserialize($meta['committer'][0]);
  85.  
  86.                 $this->summary = array_shift($lines);
  87.                 $this->detail = implode("\n", $lines);
  88.  
  89.                 $this->history = null;
  90.         }
  91.  
  92.         public function _serialize() {
  93.                 $s = '';
  94.                 $s .= sprintf("tree %s\n", bin2hex($this->tree));
  95.                 foreach ($this->parents as $parent)
  96.                         $s .= sprintf("parent %s\n", bin2hex($parent));
  97.                 $s .= sprintf("author %s\n", $this->author->serialize());
  98.                 $s .= sprintf("committer %s\n", $this->committer->serialize());
  99.                 $s .= "\n" . $this->summary . "\n" . $this->detail;
  100.                 return $s;
  101.         }
  102.  
  103.         /**
  104.          * @brief Get commit history in topological order.
  105.          *
  106.          * @returns (array of GitCommit)
  107.          */
  108.         public function getHistory() {
  109.                 if ($this->history)
  110.                         return $this->history;
  111.  
  112.                 /* count incoming edges */
  113.                 $inc = array();
  114.  
  115.                 $queue = array($this);
  116.                 while (($commit = array_shift($queue)) !== null) {
  117.                         foreach ($commit->parents as $parent) {
  118.                                 if (!isset($inc[$parent])) {
  119.                                         $inc[$parent] = 1;
  120.                                         $queue[] = $this->repo->getObject($parent);
  121.                                 } else
  122.                                         $inc[$parent]++;
  123.                         }
  124.                 }
  125.  
  126.                 $queue = array($this);
  127.                 $r = array();
  128.                 while (($commit = array_pop($queue)) !== null) {
  129.                         array_unshift($r, $commit);
  130.                         foreach ($commit->parents as $parent) {
  131.                                 if (--$inc[$parent] == 0)
  132.                                         $queue[] = $this->repo->getObject($parent);
  133.                         }
  134.                 }
  135.  
  136.                 $this->history = $r;
  137.                 return $r;
  138.         }
  139.  
  140.         /**
  141.          * @brief Get the tree referenced by this commit.
  142.          *
  143.          * @returns GitTree The GitTree referenced by this commit.
  144.          */
  145.         public function getTree() {
  146.                 return $this->repo->getObject($this->tree);
  147.         }
  148.  
  149.         /**
  150.          * @copybrief GitTree::find()
  151.          *
  152.          * This is a convenience function calling GitTree::find() on the commit's
  153.          * tree.
  154.          *
  155.          * @copydetails GitTree::find()
  156.          */
  157.         public function find($path) {
  158.                 return $this->getTree()->find($path);
  159.         }
  160.  
  161.         static public function treeDiff($a, $b) {
  162.                 return GitTree::treeDiff($a ? $a->getTree() : null, $b ? $b->getTree() : null);
  163.         }
  164. }
  165.