Subversion Repositories oidplus

Rev

Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * Copyright (C) 2008 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 GitObject
  26. {
  27.         /**
  28.          * @brief (Git) The repository this object belongs to.
  29.          */
  30.         public $repo;
  31.         protected $type;
  32.         protected $name = null;
  33.  
  34.         /**
  35.          * @brief Get the object's cached SHA-1 hash value.
  36.          *
  37.          * @returns (string) The hash value (binary sha1).
  38.          */
  39.         public function getName() {
  40.                 return $this->name;
  41.         }
  42.  
  43.         /**
  44.          * @brief Get the object's type.
  45.          *
  46.          * @returns (integer) One of Git::OBJ_COMMIT, Git::OBJ_TREE or
  47.          * GIT::OBJ_BLOB.
  48.          */
  49.         public function getType() {
  50.                 return $this->type;
  51.         }
  52.  
  53.         /**
  54.          * @brief Create a GitObject of the specified type.
  55.          *
  56.          * @param $repo (Git) The repository the object belongs to.
  57.          * @param $type (integer) Object type (one of Git::OBJ_COMMIT,
  58.          * Git::OBJ_TREE, Git::OBJ_BLOB).
  59.          * @returns GitCommit|GitTree|GitBlob  A new GitCommit, GitTree or GitBlob object respectively.
  60.          */
  61.         static public function create($repo, $type) {
  62.                 if ($type == Git::OBJ_COMMIT)
  63.                         return new GitCommit($repo);
  64.                 if ($type == Git::OBJ_TREE)
  65.                         return new GitTree($repo);
  66.                 if ($type == Git::OBJ_BLOB)
  67.                         return new GitBlob($repo);
  68.                 throw new \Exception(sprintf('unhandled object type %d', $type));
  69.         }
  70.  
  71.         /**
  72.          * @brief Internal function to calculate the hash value of a git object of the
  73.          * current type with content $data.
  74.          *
  75.          * @param $data (string) The data to hash.
  76.          * @returns (string) The hash value (binary sha1).
  77.          */
  78.         protected function hash($data) {
  79.                 $hash = hash_init('sha1');
  80.                 hash_update($hash, Git::getTypeName($this->type));
  81.                 hash_update($hash, ' ');
  82.                 hash_update($hash, "".strlen($data));
  83.                 hash_update($hash, "\0");
  84.                 hash_update($hash, $data);
  85.                 return hash_final($hash, true);
  86.         }
  87.  
  88.         /**
  89.          * @brief Internal constructor for use from derived classes.
  90.          *
  91.          * Never use this function except from a derived class. Use the
  92.          * constructor of a derived class, create() or Git::getObject() instead.
  93.          */
  94.         public function __construct($repo, $type) {
  95.                 $this->repo = $repo;
  96.                 $this->type = $type;
  97.         }
  98.  
  99.         /**
  100.          * @brief Populate this object with values from its string representation.
  101.          *
  102.          * Note that the types of $this and the serialized object in $data have to
  103.          * match.
  104.          *
  105.          * @param $data (string) The serialized representation of an object, as
  106.          * it would be stored by git.
  107.          */
  108.         public function unserialize($data) {
  109.                 $this->name = $this->hash($data);
  110.                 $this->_unserialize($data);
  111.         }
  112.  
  113.         /**
  114.          * @brief Get the string representation of an object.
  115.          *
  116.          * @returns string The serialized representation of the object, as it would be
  117.          * stored by git.
  118.          */
  119.         public function serialize() {
  120.                 return $this->_serialize();
  121.         }
  122.  
  123.         /**
  124.          * @brief Update the SHA-1 name of an object.
  125.          *
  126.          * You need to call this function after making changes to attributes in
  127.          * order to have getName() return the correct hash.
  128.          */
  129.         public function rehash() {
  130.                 $this->name = $this->hash($this->serialize());
  131.         }
  132.  
  133.         /**
  134.          * @brief Write this object in its serialized form to the git repository
  135.          * given at creation time.
  136.          */
  137.         public function write() {
  138.                 $sha1 = bin2hex($this->name);
  139.                 $path = sprintf('%s/objects/%s/%s', $this->repo->dir, substr($sha1, 0, 2), substr($sha1, 2));
  140.                 if (file_exists($path))
  141.                         return false;
  142.                 $dir = dirname($path);
  143.                 if (!is_dir($dir))
  144.                         mkdir(dirname($path), 0770);
  145.                 $f = fopen($path, 'ab');
  146.                 flock($f, LOCK_EX);
  147.                 ftruncate($f, 0);
  148.                 $data = $this->serialize();
  149.                 $data = Git::getTypeName($this->type) . ' ' . strlen($data) . "\0" . $data;
  150.                 fwrite($f, gzcompress($data));
  151.                 fclose($f);
  152.                 return true;
  153.         }
  154. }
  155.