Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1192 | daniel-mar | 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 | } |