Skip to content

Commit 35a6d1f

Browse files
mindermDan Cryer
authored and
Dan Cryer
committed
Add SVN support to PHPCI.
Closes dancryer#759
1 parent 9133c54 commit 35a6d1f

File tree

4 files changed

+188
-1
lines changed

4 files changed

+188
-1
lines changed

PHPCI/BuildFactory.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public static function getBuild(Build $base)
6161
case 'hg':
6262
$type = 'MercurialBuild';
6363
break;
64+
case 'svn':
65+
$type = 'SubversionBuild';
66+
break;
6467
}
6568

6669
$type = '\\PHPCI\\Model\\Build\\' . $type;

PHPCI/Controller/ProjectController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,11 @@ protected function projectForm($values, $type = 'add')
311311
'remote' => Lang::get('remote'),
312312
'local' => Lang::get('local'),
313313
'hg' => Lang::get('hg'),
314+
'svn' => Lang::get('svn'),
314315
);
315316

316317
$field = Form\Element\Select::create('type', Lang::get('where_hosted'), true);
317-
$field->setPattern('^(github|bitbucket|gitlab|remote|local|hg)');
318+
$field->setPattern('^(github|bitbucket|gitlab|remote|local|hg|svn)');
318319
$field->setOptions($options);
319320
$field->setClass('form-control')->setContainerClass('form-group');
320321
$form->addField($field);

PHPCI/Languages/lang.en.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
'remote' => 'Remote URL',
102102
'local' => 'Local Path',
103103
'hg' => 'Mercurial',
104+
'svn' => 'Subversion',
104105

105106
'where_hosted' => 'Where is your project hosted?',
106107
'choose_github' => 'Choose a GitHub repository:',

PHPCI/Model/Build/SubversionBuild.php

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<?php
2+
/**
3+
* PHPCI - Continuous Integration for PHP
4+
*
5+
* @copyright Copyright 2014, Block 8 Limited.
6+
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
7+
* @link https://www.phptesting.org/
8+
*/
9+
10+
namespace PHPCI\Model\Build;
11+
12+
use PHPCI\Model\Build;
13+
use PHPCI\Builder;
14+
15+
/**
16+
* Remote Subversion Build Model
17+
* @author Nadir Dzhilkibaev <[email protected]>
18+
* @package PHPCI
19+
* @subpackage Core
20+
*/
21+
class SubversionBuild extends Build
22+
{
23+
protected $svnCommand = 'svn export -q --non-interactive ';
24+
25+
/**
26+
* Get the URL to be used to clone this remote repository.
27+
*/
28+
protected function getCloneUrl()
29+
{
30+
$url = $this->getProject()->getReference();
31+
32+
if (substr($url, -1) != '/') {
33+
$url .= '/';
34+
}
35+
36+
$branch = $this->getBranch();
37+
38+
if (empty($branch) || $branch == 'trunk') {
39+
$url .= 'trunk';
40+
} else {
41+
$url .= 'branches/' . $branch;
42+
}
43+
44+
return $url;
45+
}
46+
47+
/**
48+
* @param Builder $builder
49+
*
50+
* @return void
51+
*/
52+
protected function extendSvnCommandFromConfig(Builder $builder)
53+
{
54+
$cmd = $this->svnCommand;
55+
56+
$svn = $builder->getConfig('svn');
57+
if ($svn) {
58+
foreach ($svn as $key => $value) {
59+
$cmd .= " --$key $value ";
60+
}
61+
}
62+
63+
$depth = $builder->getConfig('clone_depth');
64+
65+
if (!is_null($depth)) {
66+
$cmd .= ' --depth ' . intval($depth) . ' ';
67+
}
68+
69+
$this->svnCommand = $cmd;
70+
}
71+
72+
/**
73+
* Create a working copy by cloning, copying, or similar.
74+
*/
75+
public function createWorkingCopy(Builder $builder, $buildPath)
76+
{
77+
$this->handleConfig($builder, $buildPath);
78+
79+
$this->extendSvnCommandFromConfig($builder);
80+
81+
$key = trim($this->getProject()->getSshPrivateKey());
82+
83+
if (!empty($key)) {
84+
$success = $this->cloneBySsh($builder, $buildPath);
85+
} else {
86+
$success = $this->cloneByHttp($builder, $buildPath);
87+
}
88+
89+
if (!$success) {
90+
$builder->logFailure('Failed to export remote subversion repository.');
91+
return false;
92+
}
93+
94+
return $this->handleConfig($builder, $buildPath);
95+
}
96+
97+
/**
98+
* Use an HTTP-based svn export.
99+
*/
100+
protected function cloneByHttp(Builder $builder, $cloneTo)
101+
{
102+
$cmd = $this->svnCommand;
103+
104+
if ($this->getCommitId() != 'Manual') {
105+
$cmd .= ' -r %s %s "%s"';
106+
$success = $builder->executeCommand($cmd, $this->getCommitId(), $this->getCloneUrl(), $cloneTo);
107+
} else {
108+
$cmd .= ' %s "%s"';
109+
$success = $builder->executeCommand($cmd, $this->getCloneUrl(), $cloneTo);
110+
}
111+
112+
return $success;
113+
}
114+
115+
/**
116+
* Use an SSH-based svn export.
117+
*/
118+
protected function cloneBySsh(Builder $builder, $cloneTo)
119+
{
120+
$cmd = $this->svnCommand . ' %s "%s"';
121+
122+
if (!IS_WIN) {
123+
$keyFile = $this->writeSshKey($cloneTo);
124+
$sshWrapper = $this->writeSshWrapper($cloneTo, $keyFile);
125+
$cmd = 'export SVN_SSH="' . $sshWrapper . '" && ' . $cmd;
126+
}
127+
128+
$success = $builder->executeCommand($cmd, $this->getCloneUrl(), $cloneTo);
129+
130+
if (!IS_WIN) {
131+
// Remove the key file and svn wrapper:
132+
unlink($keyFile);
133+
unlink($sshWrapper);
134+
}
135+
136+
return $success;
137+
}
138+
139+
/**
140+
* Create an SSH key file on disk for this build.
141+
* @param $cloneTo
142+
* @return string
143+
*/
144+
protected function writeSshKey($cloneTo)
145+
{
146+
$keyPath = dirname($cloneTo . '/temp');
147+
$keyFile = $keyPath . '.key';
148+
149+
// Write the contents of this project's svn key to the file:
150+
file_put_contents($keyFile, $this->getProject()->getSshPrivateKey());
151+
chmod($keyFile, 0600);
152+
153+
// Return the filename:
154+
return $keyFile;
155+
}
156+
157+
/**
158+
* Create an SSH wrapper script for Svn to use, to disable host key checking, etc.
159+
* @param $cloneTo
160+
* @param $keyFile
161+
* @return string
162+
*/
163+
protected function writeSshWrapper($cloneTo, $keyFile)
164+
{
165+
$path = dirname($cloneTo . '/temp');
166+
$wrapperFile = $path . '.sh';
167+
168+
$sshFlags = '-o CheckHostIP=no -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o PasswordAuthentication=no';
169+
170+
// Write out the wrapper script for this build:
171+
$script = <<<OUT
172+
#!/bin/sh
173+
ssh {$sshFlags} -o IdentityFile={$keyFile} $*
174+
175+
OUT;
176+
177+
file_put_contents($wrapperFile, $script);
178+
shell_exec('chmod +x "' . $wrapperFile . '"');
179+
180+
return $wrapperFile;
181+
}
182+
}

0 commit comments

Comments
 (0)