static function status($raw = false, $cached = true)
{
$s = self::exec('status', null, null, null, false, true);
if ($raw) {
return $s;
}
if (self::$status_cache !== null && $cached) {
return self::$status_cache;
}
$st = array('branch' => null);
$i = 0;
$lines = explode("\n", rtrim($s));
$nlines = count($lines);
$st['branch'] = array_pop(explode(' ', $lines[0], 4));
$i = 1;
$line = $lines[1];
if ($line && $line[0] === '#') {
if (preg_match('/^# Your branch is ahead of \'([^\']+)\' by ([0-9]+) /', $line, $m)) {
$st['upstream'] = array('name' => $m[1], 'distance' => intval($m[2]));
}
}
$files = array();
$stage = '';
for (; $i < $nlines; $i++) {
$line = $lines[$i];
$prevstage = false;
if (!$line || $line[0] !== '#') {
break;
}
if (strlen($line) < 2) {
continue;
}
if ($line === '# Changes to be committed:') {
$prevstage = $stage;
$stage = 'staged';
} elseif ($line === '# Changed but not updated:') {
$prevstage = $stage;
$stage = 'unstaged';
} elseif ($line === '# Untracked files:') {
$prevstage = $stage;
$stage = 'untracked';
} elseif ($line[1] === "\t") {
if ($stage === 'untracked') {
$name = gb_normalize_git_name(substr($line, 2));
$files[$name] = 1;
} elseif (preg_match('/^#\\t([a-z ]+):[\\t ]+((.+) -> (.+)|.+)$/', $line, $m)) {
$status = $m[1];
if ($status === 'renamed') {
$name = gb_normalize_git_name($m[3]);
$newname = gb_normalize_git_name($m[4]);
$files[$name] = array('status' => $status, 'newname' => $newname);
} else {
if ($status === 'new file') {
$status = 'added';
}
$name = gb_normalize_git_name($m[2]);
$files[$name] = array('status' => $status);
}
}
}
# put away previous files
if ($prevstage) {
$st[$prevstage] = $files;
$files = array();
}
}
# put away last files, if any
if ($stage) {
$st[$stage] = $files;
$files = array();
}
# always save cache, even if $cached is false
self::$status_cache = $st;
return $st;
}