summaryrefslogtreecommitdiff
path: root/index.php
blob: a5342f8a1045be8bf64c2025e54949c6b3980d00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?php

function find_projects(string $path, array $projects = []): array {
  $directories = glob($path . "/{.[!.],}*", GLOB_ONLYDIR | GLOB_BRACE);
  if (($idx = array_search("$path/.git", $directories)) !== false) {
    $projects[] = substr($directories[$idx], 0, -4);
  }
  else {
    foreach ($directories as $directory) {
      $projects += find_projects($directory, $projects);
    }
  }

  return $projects;
}

$projects_path = realpath($_GET['projects']);
$projects = find_projects($projects_path);

function parse_log(): array|null {
  $proxy = md5(strval(microtime(true)));
  $process = proc_open(
    "git log " . "--pretty=format:'{%n  {$proxy}commit{$proxy}: {$proxy}%H{$proxy},%n  {$proxy}author{$proxy}: {$proxy}%aN <%aE>{$proxy},%n  {$proxy}date{$proxy}: {$proxy}%ad{$proxy},%n  {$proxy}message{$proxy}: {$proxy}%s{$proxy}%n},'",
    [
      ["pipe", "r"],
      ["pipe", "w"],
      ["pipe", "w"],
    ],
    $pipes
  );

  $output = stream_get_contents($pipes[1]);
  $string = str_replace(['"', $proxy], ['\\"', '"'], $output);
  $string = "[" . rtrim($string, ",") . "]";

  $json = json_decode($string, true);

  return $json;
}

function parse_status(): array {
  $process = proc_open(
    "git status --porcelain=v2 --branch",
    [
      ["pipe", "r"],
      ["pipe", "w"],
      ["pipe", "w"],
    ],
    $pipes
  );

  $output = stream_get_contents($pipes[1]);

  $status = ["files" => []];
  foreach (explode("\n", $output) as $line) {
    if (empty($line)) {
      continue;
    }

    $start = substr($line, 0, 1);

    if ($start == "#") {
      if (str_contains($line, "branch.oid")) {
        $status["oid"] = substr($line, strlen("# branch.oid "));
      }
      else if (str_contains($line, "branch.head")) {
        $status["head"] = substr($line, strlen("# branch.head "));
      }
      else if (str_contains($line, "branch.upstream")) {
        $status["upstream"] = substr($line, strlen("# branch.upstream "));
      }
      else if (str_contains($line, "branch.ab")) {
        $status["ab"] = substr($line, strlen("# branch.ab "));
      }
    }

    else {
      $parts = explode(" ", $line);
      $file = [
        "filename" => $parts[count($parts) - 1],
        "staged" => false,
        "unstaged" => false,
        "untracked" => false,
        "new_file" => false,
        "modified" => false,
      ];

      if ($start == "1") {
        $track_status = $parts[1];
        if (substr($track_status, 0, 1) == "A") {
          $file["staged"] = true;
          $file["new_file"] = true;
        }
        else if (substr($track_status, 0, 1) == "M") {
          $file["staged"] = true;
          $file["modified"] = true;
        }

        if (substr($track_status, 1, 1) == "M") {
          $file["unstaged"] = true;
          $file["modified"] = true;
        }

        $file = array_merge($file, [
          "previous_mode" => $parts[3],
          "new_mode" => $parts[4],
          "previous_id" => $parts[6],
          "new_id" => $parts[7],
        ]);
      }

      else if ($start == "?") {
        $file["untracked"] = true;
      }

      $status["files"][] = $file;
    }
  }

  return $status;
}

foreach ($projects as $project) {
  chdir($project);

  echo $project . "<br>";

  $status = parse_status();
  foreach ($status["files"] as $file) {
    var_dump($file);
  }

  foreach (parse_log() as $commit) {
    // echo "<a href=\"$commit[commit]\">$commit[message]</a><br>";
  }
}