Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/ssh/DiffusionGitReceivePackSSHWorkflow.php
12242 views
1
<?php
2
3
final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
4
5
protected function didConstruct() {
6
$this->setName('git-receive-pack');
7
$this->setArguments(
8
array(
9
array(
10
'name' => 'dir',
11
'wildcard' => true,
12
),
13
));
14
}
15
16
protected function executeRepositoryOperations() {
17
// This is a write, and must have write access.
18
$this->requireWriteAccess();
19
20
$is_proxy = $this->shouldProxy();
21
if ($is_proxy) {
22
return $this->executeRepositoryProxyOperations($for_write = true);
23
}
24
25
$host_wait_start = microtime(true);
26
27
$repository = $this->getRepository();
28
$viewer = $this->getSSHUser();
29
$device = AlmanacKeys::getLiveDevice();
30
31
$cluster_engine = id(new DiffusionRepositoryClusterEngine())
32
->setViewer($viewer)
33
->setRepository($repository)
34
->setLog($this);
35
36
$command = csprintf('git-receive-pack %s', $repository->getLocalPath());
37
$cluster_engine->synchronizeWorkingCopyBeforeWrite();
38
39
if ($device) {
40
$this->writeClusterEngineLogMessage(
41
pht(
42
"# Ready to receive on cluster host \"%s\".\n",
43
$device->getName()));
44
}
45
46
$log = $this->newProtocolLog($is_proxy);
47
if ($log) {
48
$this->setProtocolLog($log);
49
$log->didStartSession($command);
50
}
51
52
$caught = null;
53
try {
54
$err = $this->executeRepositoryCommand($command);
55
} catch (Exception $ex) {
56
$caught = $ex;
57
}
58
59
if ($log) {
60
$log->didEndSession();
61
}
62
63
// We've committed the write (or rejected it), so we can release the lock
64
// without waiting for the client to receive the acknowledgement.
65
$cluster_engine->synchronizeWorkingCopyAfterWrite();
66
67
if ($caught) {
68
throw $caught;
69
}
70
71
if (!$err) {
72
$this->waitForGitClient();
73
74
// When a repository is clustered, we reach this cleanup code on both
75
// the proxy and the actual final endpoint node. Don't do more cleanup
76
// or logging than we need to.
77
$repository->writeStatusMessage(
78
PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
79
PhabricatorRepositoryStatusMessage::CODE_OKAY);
80
81
$host_wait_end = microtime(true);
82
83
$this->updatePushLogWithTimingInformation(
84
$this->getClusterEngineLogProperty('writeWait'),
85
$this->getClusterEngineLogProperty('readWait'),
86
($host_wait_end - $host_wait_start));
87
}
88
89
return $err;
90
}
91
92
private function executeRepositoryCommand($command) {
93
$repository = $this->getRepository();
94
$command = PhabricatorDaemon::sudoCommandAsDaemonUser($command);
95
96
$future = id(new ExecFuture('%C', $command))
97
->setEnv($this->getEnvironment());
98
99
return $this->newPassthruCommand()
100
->setIOChannel($this->getIOChannel())
101
->setCommandChannelFromExecFuture($future)
102
->execute();
103
}
104
105
private function updatePushLogWithTimingInformation(
106
$write_wait,
107
$read_wait,
108
$host_wait) {
109
110
if ($write_wait !== null) {
111
$write_wait = (int)(1000000 * $write_wait);
112
}
113
114
if ($read_wait !== null) {
115
$read_wait = (int)(1000000 * $read_wait);
116
}
117
118
if ($host_wait !== null) {
119
$host_wait = (int)(1000000 * $host_wait);
120
}
121
122
$identifier = $this->getRequestIdentifier();
123
124
$event = new PhabricatorRepositoryPushEvent();
125
$conn = $event->establishConnection('w');
126
127
queryfx(
128
$conn,
129
'UPDATE %T SET writeWait = %nd, readWait = %nd, hostWait = %nd
130
WHERE requestIdentifier = %s',
131
$event->getTableName(),
132
$write_wait,
133
$read_wait,
134
$host_wait,
135
$identifier);
136
}
137
138
}
139
140