GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#1264)
by
unknown
02:56
created

functions.php ➔ download()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 14

Duplication

Lines 20
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 4
nop 3
dl 20
loc 20
ccs 0
cts 0
cp 0
crap 30
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/* (c) Anton Medvedev <[email protected]>
3
 *
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
8
namespace Deployer;
9
10
use Deployer\Host\FileLoader;
11
use Deployer\Host\Host;
12
use Deployer\Host\Localhost;
13
use Deployer\Host\Range;
14
use Deployer\Support\Proxy;
15
use Deployer\Task\Context;
16
use Deployer\Task\GroupTask;
17
use Deployer\Task\Task as T;
18
use Deployer\Type\Result;
19
use Symfony\Component\Console\Input\InputArgument;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
22
use Symfony\Component\Console\Output\OutputInterface;
23
use Symfony\Component\Console\Question\ChoiceQuestion;
24
use Symfony\Component\Console\Question\ConfirmationQuestion;
25
use Symfony\Component\Console\Question\Question;
26
27
// There are two types of functions: Deployer dependent and Context dependent.
28
// Deployer dependent function uses in definition stage of recipe and may require Deployer::get() method.
29
// Context dependent function uses while task execution and must require only Context::get() method.
30
// But there is also a third type of functions: mixed. Mixed function uses in definition stage and in task
31
// execution stage. They are acts like two different function, but have same name. Example of such function
32
// is set() func. This function determine in which stage it was called by Context::get() method.
33
34
/**
35
 * @param array ...$hostnames
36
 * @return Host|Host[]|Proxy
37
 */
38
function host(...$hostnames)
39
{
40 2
    $deployer = Deployer::get();
41 2
    $hostnames = Range::expand($hostnames);
42
43
    // Return hosts if has
44 2
    if ($deployer->hosts->has($hostnames[0])) {
45 2
        if (count($hostnames) === 1) {
46 1
            return $deployer->hosts->get($hostnames[0]);
47
        } else {
48 1
            return array_map([$deployer->hosts, 'get'], $hostnames);
49
        }
50
    }
51
52
    // Add otherwise
53 1
    if (count($hostnames) === 1) {
54 1
        $host = new Host($hostnames[0]);
55 1
        $deployer->hosts->set($hostnames[0], $host);
56 1
        return $host;
57
    } else {
58
        $hosts = array_map(function ($hostname) use ($deployer) {
59 1
            $host = new Host($hostname);
60 1
            $deployer->hosts->set($hostname, $host);
61 1
            return $host;
62 1
        }, $hostnames);
63 1
        return new Proxy($hosts);
64
    }
65
}
66
67
/**
68
 * @param array ...$hostnames
69
 * @return Localhost|Localhost[]|Proxy
70
 */
71
function localhost(...$hostnames)
72
{
73 9
    $deployer = Deployer::get();
74 9
    $hostnames = Range::expand($hostnames);
75
76 9
    if (count($hostnames) <= 1) {
77 8
        $host = count($hostnames) === 1 ? new Localhost($hostnames[0]) : new Localhost();
78 8
        $deployer->hosts->set($host->getHostname(), $host);
79 8
        return $host;
80
    } else {
81
        $hosts = array_map(function ($hostname) use ($deployer) {
82 1
            $host = new Localhost($hostname);
83 1
            $deployer->hosts->set($host->getHostname(), $host);
84 1
            return $host;
85 1
        }, $hostnames);
86 1
        return new Proxy($hosts);
87
    }
88
}
89
90
/**
91
 * Load list of hosts from file
92
 *
93
 * @param string $file
94
 */
95
function inventory($file)
96
{
97 1
    $deployer = Deployer::get();
98 1
    $fileLoader = new FileLoader();
99 1
    $fileLoader->load($file);
100
101 1
    foreach ($fileLoader->getHosts() as $host) {
102 1
        $deployer->hosts->set($host->getHostname(), $host);
103
    }
104 1
}
105
106
/**
107
 * Set task description.
108
 *
109
 * @param string $title
110
 * @return string
111
 */
112
function desc($title = null)
113
{
114 11
    static $store = null;
115
116 11
    if ($title === null) {
117 11
        return $store;
118
    } else {
119 7
        return $store = $title;
120
    }
121
}
122
123
/**
124
 * Define a new task and save to tasks list.
125
 *
126
 * Alternatively get a defined task.
127
 *
128
 * @param string $name Name of current task.
129
 * @param callable|array|string|null $body Callable task, array of other tasks names or nothing to get a defined tasks
130
 * @return Task\Task
131
 * @throws \InvalidArgumentException
132
 */
133
function task($name, $body = null)
134
{
135 11
    $deployer = Deployer::get();
136
137 11
    if (empty($body)) {
138 1
        $task = $deployer->tasks->get($name);
139 1
        return $task;
140
    }
141
142 11
    if ($body instanceof \Closure) {
143 8
        $task = new T($name, $body);
144 11
    } elseif (is_array($body)) {
145 9
        $task = new GroupTask($name, $body);
146 10
    } elseif (is_string($body)) {
147
        $task = new T($name, function () use ($body) {
148 1
            cd('{{release_path}}');
149 1
            run($body);
150 10
        });
151
    } else {
152
        throw new \InvalidArgumentException('Task should be an closure or array of other tasks.');
153
    }
154
155 11
    $deployer->tasks->set($name, $task);
156
157 11
    if (!empty(desc())) {
158 7
        $task->desc(desc());
159 7
        desc(''); // Clear title.
160
    }
161
162 11
    return $task;
163
}
164
165
/**
166
 * Call that task before specified task runs.
167
 *
168
 * @param string $it
169
 * @param string $that
170
 */
171
function before($it, $that)
172
{
173 1
    $deployer = Deployer::get();
174 1
    $beforeTask = $deployer->tasks->get($it);
175
176 1
    $beforeTask->addBefore($that);
177 1
}
178
179
/**
180
 * Call that task after specified task runs.
181
 *
182
 * @param string $it
183
 * @param string $that
184
 */
185
function after($it, $that)
186
{
187 1
    $deployer = Deployer::get();
188 1
    $afterTask = $deployer->tasks->get($it);
189
190 1
    $afterTask->addAfter($that);
191 1
}
192
193
/**
194
 * Setup which task run on failure of first.
195
 *
196
 * @param string $it
197
 * @param string $that
198
 */
199
function fail($it, $that)
200
{
201 7
    $deployer = Deployer::get();
202 7
    $deployer['fail']->set($it, $that);
203 7
}
204
205
/**
206
 * Add users arguments.
207
 *
208
 * Note what Deployer already has one argument: "stage".
209
 *
210
 * @param string $name
211
 * @param int $mode
212
 * @param string $description
213
 * @param mixed $default
214
 */
215
function argument($name, $mode = null, $description = '', $default = null)
216
{
217
    Deployer::get()->getConsole()->getUserDefinition()->addArgument(
218
        new InputArgument($name, $mode, $description, $default)
219
    );
220
}
221
222
/**
223
 * Add users options.
224
 *
225
 * @param string $name
226
 * @param string $shortcut
227
 * @param int $mode
228
 * @param string $description
229
 * @param mixed $default
230
 */
231
function option($name, $shortcut = null, $mode = null, $description = '', $default = null)
232
{
233 7
    Deployer::get()->getConsole()->getUserDefinition()->addOption(
234 7
        new InputOption($name, $shortcut, $mode, $description, $default)
235
    );
236 7
}
237
238
/**
239
 * Change the current working directory.
240
 *
241
 * @param string $path
242
 */
243
function cd($path)
244
{
245 5
    set('working_path', parse($path));
246 5
}
247
248
/**
249
 * Execute a callback within a specific directory and revert back to the initial working directory.
250
 *
251
 * @param string $path
252
 * @param callable $callback
253
 */
254
function within($path, $callback)
255
{
256
    $lastWorkingPath = get('working_path', '');
257
    set('working_path', parse($path));
258
    $callback();
259
    set('working_path', $lastWorkingPath);
260
}
261
262
/**
263
 * Return the current working path.
264
 *
265
 * @deprecated Will be removed in 6.x
266
 * @return string
267
 */
268
function workingPath()
269
{
270
    return get('working_path', false);
271
}
272
273
/**
274
 * Run command.
275
 *
276
 * @param string $command
277
 * @param array $options
278
 * @return Result
279
 */
280
function run($command, $options = [])
281
{
282 6
    $client = Deployer::get()->sshClient;
283 6
    $process = Deployer::get()->processRunner;
284 6
    $host = Context::get()->getHost();
285 6
    $hostname = $host->getHostname();
286
287 6
    $command = parse($command);
288 6
    $workingPath = get('working_path', '');
289
290 6
    if (!empty($workingPath)) {
291 5
        $command = "cd $workingPath && ($command)";
292
    }
293
294 6
    if ($host instanceof Localhost) {
295 6
        $output = $process->run($hostname, $command, $options);
296
    } else {
297
        $output = $client->run($host, $command, $options);
298
    }
299
300 6
    return new Result($output);
301
}
302
303
/**
304
 * Execute commands on local machine
305
 *
306
 * @param string $command Command to run locally.
307
 * @param array $options
308
 * @return Result Output of command.
309
 */
310
function runLocally($command, $options = [])
311
{
312 1
    $process = Deployer::get()->processRunner;
313 1
    $hostname = 'localhost';
314
315 1
    $workingPath = get('working_path', '');
316 1
    $command = parse($command);
317
318 1
    if (!empty($workingPath)) {
319
        $command = "cd $workingPath && ($command)";
320
    }
321
322 1
    $output = $process->run($hostname, $command, $options);
323
324 1
    return new Result($output);
325
}
326
327
/**
328
 * Run test command.
329
 * Example:
330
 *
331
 *     test('[ -d {{release_path}} ]')
332
 *
333
 * @param string $command
334
 * @return bool
335
 */
336
function test($command)
337
{
338 4
    return run("if $command; then echo 'true'; fi")->toBool();
339
}
340
341
/**
342
 * Run test command locally.
343
 * Example:
344
 *
345
 *     testLocally('[ -d {{local_release_path}} ]')
346
 *
347
 * @param string $command
348
 * @return bool
349
 */
350
function testLocally($command)
351
{
352
    return runLocally("if $command; then echo 'true'; fi")->toBool();
353
}
354
355
/**
356
 * Iterate other hosts, allowing to call run func in callback.
357
 *
358
 * @experimental
359
 * @param Host|Host[] $hosts
360
 * @param callable $callback
361
 */
362
function on($hosts, callable $callback)
363
{
364 3
    $input = Context::has() ? input() : null;
365 3
    $output = Context::has() ? output() : null;
366
367 3
    if (!is_array($hosts) && !($hosts instanceof \Traversable)) {
368
        $hosts = [$hosts];
369
    }
370
371 3
    foreach ($hosts as $host) {
372 3
        if ($host instanceof Host) {
373 3
            Context::push(new Context($host, $input, $output));
374 3
            $callback($host);
375 3
            Context::pop();
376
        } else {
377 3
            throw new \InvalidArgumentException("Function on can iterate only on Host instances.");
378
        }
379
    }
380 3
}
381
382
/**
383
 * Return hosts based on roles.
384
 *
385
 * @experimental
386
 * @param string[] $roles
387
 * @return Host[]
388
 */
389
function roles(...$roles)
390
{
391
    return Deployer::get()->hostSelector->getByRoles($roles);
392
}
393
394
/**
395
 * Run task
396
 *
397
 * @experimental
398
 * @param string $task
399
 */
400
function invoke($task)
401
{
402
    $informer = Deployer::get()->informer;
403
    $task = Deployer::get()->tasks->get($task);
404
    $input = Context::get()->getInput();
405
    $output = Context::get()->getOutput();
406
    $host = Context::get()->getHost();
407
408
    $informer->startTask($task->getName());
409
    $task->run(new Context($host, $input, $output));
410
    $informer->endTask();
411
}
412
413
/**
414
 * Upload file or directory to host
415
 *
416
 * @param string $source
417
 * @param string $destination
418
 * @param array $config
419
 */
420 View Code Duplication
function upload($source, $destination, array $config = [])
421
{
422
    $rsync = Deployer::get()->rsync;
423
    $host = Context::get()->getHost();
424
    $source = parse($source);
425
    $destination = parse($destination);
426
427
    if ($host instanceof Localhost) {
428
        $rsync->call($host->getHostname(), $source, $destination, $config);
429
    } else {
430
        $sshArguments = $host->getSshArguments()->getCliArguments();
431
        if (empty($sshArguments) === false) {
432
            if (!isset($config['options']) || !is_array($config['options'])) {
433
                $config['options'] = [];
434
            }
435
            $config['options'][] = "-e 'ssh $sshArguments'";
436
        }
437
        $rsync->call($host->getHostname(), $source, "$host:$destination", $config);
438
    }
439
}
440
441
/**
442
 * Download file or directory from host
443
 *
444
 * @param string $destination
445
 * @param string $source
446
 * @param array $config
447
 */
448 View Code Duplication
function download($source, $destination, array $config = [])
449
{
450
    $rsync = Deployer::get()->rsync;
451
    $host = Context::get()->getHost();
452
    $source = parse($source);
453
    $destination = parse($destination);
454
455
    if ($host instanceof Localhost) {
456
        $rsync->call($host->getHostname(), $source, $destination, $config);
457
    } else {
458
        $sshArguments = $host->getSshArguments()->getCliArguments();
459
        if (empty($sshArguments) === false) {
460
            if (!isset($config['options']) || !is_array($config['options'])) {
461
                $config['options'] = [];
462
            }
463
            $config['options'][] = "-e 'ssh $sshArguments'";
464
        }
465
        $rsync->call($host->getHostname(), "$host:$source", $destination, $config);
466
    }
467
}
468
469
/**
470
 * Writes a message to the output and adds a newline at the end.
471
 * @param string|array $message
472
 * @param int $options
473
 */
474
function writeln($message, $options = 0)
475
{
476 1
    output()->writeln(parse($message), $options);
477 1
}
478
479
/**
480
 * Writes a message to the output.
481
 * @param string $message
482
 * @param int $options
483
 */
484
function write($message, $options = 0)
485
{
486
    output()->write(parse($message), $options);
487
}
488
489
/**
490
 * Setup configuration option.
491
 *
492
 * @param string $name
493
 * @param mixed $value
494
 */
495
function set($name, $value)
496
{
497 8
    if (!Context::has()) {
498 8
        Deployer::setDefault($name, $value);
499
    } else {
500 5
        Context::get()->getConfig()->set($name, $value);
501
    }
502 8
}
503
504
/**
505
 * Merge new config params to existing config array.
506
 *
507
 * @param string $name
508
 * @param array $array
509
 */
510
function add($name, $array)
511
{
512
    if (!Context::has()) {
513
        Deployer::addDefault($name, $array);
514
    } else {
515
        Context::get()->getConfig()->add($name, $array);
516
    }
517
}
518
519
/**
520
 * Get configuration value.
521
 *
522
 * @param string $name
523
 * @param mixed|null $default
524
 * @return mixed
525
 */
526
function get($name, $default = null)
527
{
528 7
    if (!Context::has()) {
529
        return Deployer::getDefault($name, $default);
530
    } else {
531 7
        return Context::get()->getConfig()->get($name, $default);
532
    }
533
}
534
535
/**
536
 * Check if there is such configuration option.
537
 *
538
 * @param string $name
539
 * @return boolean
540
 */
541
function has($name)
542
{
543
    if (!Context::has()) {
544
        return Deployer::hasDefault($name);
545
    } else {
546
        return Context::get()->getConfig()->has($name);
547
    }
548
}
549
550
/**
551
 * @param string $message
552
 * @param string|null $default
553
 * @param string[]|null $suggestedChoices
554
 * @return string
555
 * @codeCoverageIgnore
556
 */
557
function ask($message, $default = null, $suggestedChoices = null)
558
{
559
    Context::required(__FUNCTION__);
560
561
    if (($suggestedChoices !== null) && (empty($suggestedChoices))) {
562
        throw new \InvalidArgumentException('Suggested choices should not be empty');
563
    }
564
565
    if (isQuiet()) {
566
        return $default;
567
    }
568
569
    $helper = Deployer::get()->getHelper('question');
570
571
    $message = "<question>$message" . (($default === null) ? "" : " [$default]") . "</question> ";
572
573
    $question = new Question($message, $default);
574
575
    if (empty($suggestedChoices) === false) {
576
        $question->setAutocompleterValues($suggestedChoices);
577
    }
578
579
    return $helper->ask(input(), output(), $question);
580
}
581
582
/**
583
 * @param string $message
584
 * @param string[] $availableChoices
585
 * @param string|null $default
586
 * @param bool|false $multiselect
587
 * @return array
588
 * @codeCoverageIgnore
589
 */
590
function askChoice($message, array $availableChoices, $default = null, $multiselect = false)
591
{
592
    Context::required(__FUNCTION__);
593
594
    if (empty($availableChoices)) {
595
        throw new \InvalidArgumentException('Available choices should not be empty');
596
    }
597
598
    if ($default !== null && !array_key_exists($default, $availableChoices)) {
599
        throw new \InvalidArgumentException('Default choice is not available');
600
    }
601
602
    if (isQuiet()) {
603
        if ($default === null) {
604
            $default = key($availableChoices);
605
        }
606
        return [$default => $availableChoices[$default]];
607
    }
608
609
    $helper = Deployer::get()->getHelper('question');
610
611
    $message = "<question>$message" . (($default === null) ? "" : " [$default]") . "</question> ";
612
613
    $question = new ChoiceQuestion($message, $availableChoices, $default);
614
    $question->setMultiselect($multiselect);
615
616
    return $helper->ask(input(), output(), $question);
617
}
618
619
/**
620
 * @param string $message
621
 * @param bool $default
622
 * @return bool
623
 * @codeCoverageIgnore
624
 */
625
function askConfirmation($message, $default = false)
626
{
627
    Context::required(__FUNCTION__);
628
629
    if (isQuiet()) {
630
        return $default;
631
    }
632
633
    $helper = Deployer::get()->getHelper('question');
634
635
    $yesOrNo = $default ? 'Y/n' : 'y/N';
636
    $message = "<question>$message [$yesOrNo]</question> ";
637
638
    $question = new ConfirmationQuestion($message, $default);
639
640
    return $helper->ask(input(), output(), $question);
641
}
642
643
/**
644
 * @param string $message
645
 * @return string
646
 * @codeCoverageIgnore
647
 */
648
function askHiddenResponse($message)
649
{
650
    Context::required(__FUNCTION__);
651
652
    if (isQuiet()) {
653
        return '';
654
    }
655
656
    $helper = Deployer::get()->getHelper('question');
657
658
    $message = "<question>$message</question> ";
659
660
    $question = new Question($message);
661
    $question->setHidden(true);
662
    $question->setHiddenFallback(false);
663
664
    return $helper->ask(input(), output(), $question);
665
}
666
667
/**
668
 * @return InputInterface
669
 */
670
function input()
671
{
672 4
    return Context::get()->getInput();
673
}
674
675
676
/**
677
 * @return OutputInterface
678
 */
679
function output()
680
{
681 2
    return Context::get()->getOutput();
682
}
683
684
/**
685
 * @return bool
686
 */
687
function isQuiet()
688
{
689
    return OutputInterface::VERBOSITY_QUIET === output()->getVerbosity();
690
}
691
692
693
/**
694
 * @return bool
695
 */
696
function isVerbose()
697
{
698 1
    return OutputInterface::VERBOSITY_VERBOSE <= output()->getVerbosity();
699
}
700
701
702
/**
703
 * @return bool
704
 */
705
function isVeryVerbose()
706
{
707
    return OutputInterface::VERBOSITY_VERY_VERBOSE <= output()->getVerbosity();
708
}
709
710
711
/**
712
 * @return bool
713
 */
714
function isDebug()
715
{
716
    return OutputInterface::VERBOSITY_DEBUG <= output()->getVerbosity();
717
}
718
719
/**
720
 * Check if command exists
721
 *
722
 * @param string $command
723
 * @return bool
724
 */
725
function commandExist($command)
726
{
727 3
    return run("if hash $command 2>/dev/null; then echo 'true'; fi")->toBool();
728
}
729
730
function commandSupportsOption($command, $option)
731
{
732 4
    return test("[[ $(man $command 2>&1 || $command -h 2>&1 || $command --help 2>&1) =~ '$option' ]]");
733
}
734
735
/**
736
 * Parse set values.
737
 *
738
 * @param string $value
739
 * @return string
740
 */
741
function parse($value)
742
{
743 7
    return Context::get()->getConfig()->parse($value);
744
}
745
746
function locateBinaryPath($name)
747
{
748 3
    $nameEscaped = escapeshellarg($name);
749
750
    // Try `command`, should cover all Bourne-like shells
751 3
    if (commandExist("command")) {
752 3
        return run("command -v $nameEscaped")->toString();
753
    }
754
755
    // Try `which`, should cover most other cases
756
    if (commandExist("which")) {
757
        return run("which $nameEscaped")->toString();
758
    }
759
760
    // Fallback to `type` command, if the rest fails
761
    if (commandExist("type")) {
762
        $result = run("type -p $nameEscaped")->toString();
763
764
        if ($result) {
765
            // Deal with issue when `type -p` outputs something like `type -ap` in some implementations
766
            return trim(str_replace("$name is", "", $result));
767
        }
768
    }
769
770
    throw new \RuntimeException("Can't locate [$nameEscaped] - neither of [command|which|type] commands are available");
771
}
772