Subversion Repositories oidplus

Rev

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
}