Index: ps/trunk/build/jenkins/lint-patch.sh
===================================================================
--- ps/trunk/build/jenkins/lint-patch.sh (revision 23970)
+++ ps/trunk/build/jenkins/lint-patch.sh (nonexistent)
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-# Lint errors should not count as build failures
-set +e
-set -v
-
-# Move to the root of the repository (this script is in build/jenkins/)
-cd "$(dirname $0)"/../../
-
-arc patch --diff "$DIFF_ID" --force
-
-svn st | grep '^[AM]' | cut -c 9- | xargs coala --ci --flush-cache --limit-files > .phabricator-comment
Property changes on: ps/trunk/build/jenkins/lint-patch.sh
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Index: ps/trunk/build/jenkins/lint-config/eslintrc.json
===================================================================
--- ps/trunk/build/jenkins/lint-config/eslintrc.json (revision 23970)
+++ ps/trunk/build/jenkins/lint-config/eslintrc.json (nonexistent)
@@ -1,97 +0,0 @@
-{
- "parserOptions": {
- "ecmaVersion": 6
- },
- "plugins": [
- "brace-rules"
- ],
- "rules": {
- "no-caller": 1,
- "no-cond-assign": 1,
- "no-constant-condition": ["error", { "checkLoops": false }],
- "no-dupe-args": 1,
- "no-dupe-keys": 1,
- "no-duplicate-case": 1,
- "no-empty": 1,
- "no-extra-boolean-cast": 0,
- "no-extra-parens": 0,
- "no-extra-semi": 1,
- "no-floating-decimal": 1,
- "no-func-assign": 1,
- "no-negated-in-lhs": 1,
- "no-obj-calls": 1,
- "no-unreachable": 1,
- "no-use-before-define": ["error", "nofunc"],
- "use-isnan": 1,
- "valid-jsdoc": 0,
- "valid-typeof": 1,
-
- "block-scoped-var": 0,
- "consistent-return": 1,
- "default-case": 1,
- "dot-notation": 1,
- "no-else-return": 1,
- "no-invalid-this": 1,
- "no-loop-func": 0,
- "no-multi-spaces": ["warn", { "ignoreEOLComments": true }],
- "no-new": 1,
- "no-redeclare": 0,
- "no-return-assign": 1,
- "no-self-assign": 1,
- "no-self-compare": 1,
- "no-unmodified-loop-condition": 1,
- "no-unused-expressions": 1,
- "no-unused-labels": 1,
- "no-useless-concat": 0,
- "yoda": 1,
-
- "no-delete-var": 1,
- "no-label-var": 1,
- "no-shadow-restricted-names": 1,
- "no-shadow": 1,
- "no-undef": 0,
- "no-undef-init": 1,
- "no-unused-vars": 0,
-
- "comma-spacing": 1,
- "indent": ["warn", "tab", { "outerIIFEBody": 0 }],
- "key-spacing": 1,
- "new-cap": 0,
- "new-parens": 1,
- "no-mixed-spaces-and-tabs": ["warn", "smart-tabs"],
- "no-multi-assign": 1,
- "no-trailing-spaces": 1,
- "no-unneeded-ternary": 1,
- "no-irregular-whitespace": 1,
- "object-curly-spacing": ["warn", "always"],
- "operator-assignment": 1,
- "operator-linebreak": ["warn", "after"],
- "quote-props": 1,
- "semi": 1,
- "semi-spacing": 1,
- "space-before-function-paren": ["warn", "never"],
- "space-in-parens": 1,
- "space-unary-ops": 1,
- "spaced-comment": ["warn", "always"],
-
- "no-class-assign": 1,
- "no-const-assign": 1,
- "no-dupe-class-members" : 1,
- "prefer-const": 0,
-
- "brace-rules/brace-on-same-line": ["warn", {
- "FunctionDeclaration": "never",
- "FunctionExpression": "ignore",
- "ArrowFunctionExpression": "always",
- "IfStatement": "never",
- "TryStatement": "ignore",
- "CatchClause": "ignore",
- "DoWhileStatement": "never",
- "WhileStatement": "never",
- "ForStatement": "never",
- "ForInStatement": "never",
- "ForOfStatement": "never",
- "SwitchStatement": "never"
- }, { "allowSingleLine": true }]
- }
-}
Property changes on: ps/trunk/build/jenkins/lint-config/eslintrc.json
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Index: ps/trunk/build/jenkins/lint-config/jshintrc.json
===================================================================
--- ps/trunk/build/jenkins/lint-config/jshintrc.json (revision 23970)
+++ ps/trunk/build/jenkins/lint-config/jshintrc.json (nonexistent)
@@ -1,11 +0,0 @@
-{
- "esversion": 6,
- "eqeqeq": false,
- "freeze": true,
- "latedef": "nofunc",
- "loopfunc": true,
- "noarg": true,
- "nonbsp": true,
- "undef": false,
- "unused": false
-}
Property changes on: ps/trunk/build/jenkins/lint-config/jshintrc.json
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Index: ps/trunk/.coafile
===================================================================
--- ps/trunk/.coafile (revision 23970)
+++ ps/trunk/.coafile (revision 23971)
@@ -1,10 +1,11 @@
[Source]
bears = CPPCheckBear, LicenseYearBear
+language = c++
files = source/**.(cpp|h)
-ignore = source/third_party/**
+ignore = source/third_party
[JS]
bears = ESLintBear, JSHintBear
-eslint_config = build/jenkins/lint-config/eslintrc.json
-jshint_config = build/jenkins/lint-config/jshintrc.json
+eslint_config = build/coala/lint-config/eslintrc.json
+jshint_config = build/coala/lint-config/jshintrc.json
files = binaries/data/**.js
Index: ps/trunk/build/coala/LicenseYearBear.py
===================================================================
--- ps/trunk/build/coala/LicenseYearBear.py (revision 23970)
+++ ps/trunk/build/coala/LicenseYearBear.py (revision 23971)
@@ -1,59 +1,59 @@
from coalib.bears.LocalBear import LocalBear
from coalib.results.Result import Result
from os.path import getmtime
from re import compile
from datetime import date
# Requires https://pypi.python.org/pypi/svn
from svn.local import LocalClient
from svn.exception import SvnException
class LicenseYearBear(LocalBear):
"""
Detects a wrong year of a license header
"""
LANGUAGES = {'C', 'C++'}
AUTHORS = {'Vladislav Belov'}
LICENSE = 'GPL-2.0'
CAN_DETECT = {'Documentation', 'Formatting'}
def get_last_modification(self, filename):
client = LocalClient(filename)
was_modified = False
for status in client.status():
if status.type_raw_name == 'modified':
was_modified = True
break
if not was_modified:
try:
return client.info()['commit_date'].year
- except SvnException:
+ except (AttributeError, SvnException):
return None
else:
return date.today().year
def run(self, filename, file):
modification_year = self.get_last_modification(filename)
if not modification_year:
return
license_regexp = compile('/\* Copyright \([cC]?\) ([\d]+) Wildfire Games')
for line_number, line in enumerate(file):
match = license_regexp.search(line)
if not match:
break
license_year = match.group(1)
if not license_year:
break
license_year = int(license_year)
if modification_year == license_year:
break
return [Result.from_values(origin=self,
message='License should have "%d" year instead of "%d"' % (modification_year, license_year),
file=filename, line=line_number + 1)]
Index: ps/trunk/build/coala/lint-config/eslintrc.json
===================================================================
--- ps/trunk/build/coala/lint-config/eslintrc.json (nonexistent)
+++ ps/trunk/build/coala/lint-config/eslintrc.json (revision 23971)
@@ -0,0 +1,97 @@
+{
+ "parserOptions": {
+ "ecmaVersion": 6
+ },
+ "plugins": [
+ "brace-rules"
+ ],
+ "rules": {
+ "no-caller": 1,
+ "no-cond-assign": 1,
+ "no-constant-condition": ["error", { "checkLoops": false }],
+ "no-dupe-args": 1,
+ "no-dupe-keys": 1,
+ "no-duplicate-case": 1,
+ "no-empty": 1,
+ "no-extra-boolean-cast": 0,
+ "no-extra-parens": 0,
+ "no-extra-semi": 1,
+ "no-floating-decimal": 1,
+ "no-func-assign": 1,
+ "no-negated-in-lhs": 1,
+ "no-obj-calls": 1,
+ "no-unreachable": 1,
+ "no-use-before-define": ["error", "nofunc"],
+ "use-isnan": 1,
+ "valid-jsdoc": 0,
+ "valid-typeof": 1,
+
+ "block-scoped-var": 0,
+ "consistent-return": 1,
+ "default-case": 1,
+ "dot-notation": 1,
+ "no-else-return": 1,
+ "no-invalid-this": 1,
+ "no-loop-func": 0,
+ "no-multi-spaces": ["warn", { "ignoreEOLComments": true }],
+ "no-new": 1,
+ "no-redeclare": 0,
+ "no-return-assign": 1,
+ "no-self-assign": 1,
+ "no-self-compare": 1,
+ "no-unmodified-loop-condition": 1,
+ "no-unused-expressions": 1,
+ "no-unused-labels": 1,
+ "no-useless-concat": 0,
+ "yoda": 1,
+
+ "no-delete-var": 1,
+ "no-label-var": 1,
+ "no-shadow-restricted-names": 1,
+ "no-shadow": 1,
+ "no-undef": 0,
+ "no-undef-init": 1,
+ "no-unused-vars": 0,
+
+ "comma-spacing": 1,
+ "indent": ["warn", "tab", { "outerIIFEBody": 0 }],
+ "key-spacing": 1,
+ "new-cap": 0,
+ "new-parens": 1,
+ "no-mixed-spaces-and-tabs": ["warn", "smart-tabs"],
+ "no-multi-assign": 1,
+ "no-trailing-spaces": 1,
+ "no-unneeded-ternary": 1,
+ "no-irregular-whitespace": 1,
+ "object-curly-spacing": ["warn", "always"],
+ "operator-assignment": 1,
+ "operator-linebreak": ["warn", "after"],
+ "quote-props": 1,
+ "semi": 1,
+ "semi-spacing": 1,
+ "space-before-function-paren": ["warn", "never"],
+ "space-in-parens": 1,
+ "space-unary-ops": 1,
+ "spaced-comment": ["warn", "always"],
+
+ "no-class-assign": 1,
+ "no-const-assign": 1,
+ "no-dupe-class-members" : 1,
+ "prefer-const": 0,
+
+ "brace-rules/brace-on-same-line": ["warn", {
+ "FunctionDeclaration": "never",
+ "FunctionExpression": "ignore",
+ "ArrowFunctionExpression": "always",
+ "IfStatement": "never",
+ "TryStatement": "ignore",
+ "CatchClause": "ignore",
+ "DoWhileStatement": "never",
+ "WhileStatement": "never",
+ "ForStatement": "never",
+ "ForInStatement": "never",
+ "ForOfStatement": "never",
+ "SwitchStatement": "never"
+ }, { "allowSingleLine": true }]
+ }
+}
Property changes on: ps/trunk/build/coala/lint-config/eslintrc.json
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/build/coala/lint-config/jshintrc.json
===================================================================
--- ps/trunk/build/coala/lint-config/jshintrc.json (nonexistent)
+++ ps/trunk/build/coala/lint-config/jshintrc.json (revision 23971)
@@ -0,0 +1,11 @@
+{
+ "esversion": 6,
+ "eqeqeq": false,
+ "freeze": true,
+ "latedef": "nofunc",
+ "loopfunc": true,
+ "noarg": true,
+ "nonbsp": true,
+ "undef": false,
+ "unused": false
+}
Property changes on: ps/trunk/build/coala/lint-config/jshintrc.json
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/build/jenkins/dockerfiles/coala.Dockerfile
===================================================================
--- ps/trunk/build/jenkins/dockerfiles/coala.Dockerfile (revision 23970)
+++ ps/trunk/build/jenkins/dockerfiles/coala.Dockerfile (revision 23971)
@@ -1,10 +1,22 @@
-FROM python:3.7-alpine
+FROM python:3.8
-RUN adduser -u 1006 -D builder
+RUN useradd --uid 1006 builder
-RUN apk add subversion cppcheck npm
+RUN apt-get -yy update && apt-get -yy install \
+ cppcheck \
+ git \
+ npm \
+ subversion
-RUN pip3 install coala-bears svn
+RUN npm install -g npm@latest
RUN npm install -g eslint@5.16.0 jshint eslint-plugin-brace-rules
+RUN pip3 install svn
+
+RUN git clone -b 0ad-fixes https://github.com/0ad/coala.git
+RUN cd coala && pip3 install .
+
+RUN git clone -b 0ad-fixes https://github.com/0ad/coala-bears.git
+RUN cd coala-bears && pip3 install .
+
USER builder
Index: ps/trunk/build/jenkins/pipelines/docker-differential.Jenkinsfile
===================================================================
--- ps/trunk/build/jenkins/pipelines/docker-differential.Jenkinsfile (revision 23970)
+++ ps/trunk/build/jenkins/pipelines/docker-differential.Jenkinsfile (revision 23971)
@@ -1,160 +1,198 @@
-/* Copyright (C) 2019 Wildfire Games.
+/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
// This pipeline is used to build patches on various compilers.
def compilers = ["gcc6"]
def patchesMap = compilers.collectEntries {
["${it}": patch(it)]
}
def patch(compiler) {
return {
stage("Patch: ${compiler}") {
try {
ws("/zpool0/${compiler}") {
sh "arc patch --diff ${params.DIFF_ID} --force"
}
} catch(e) {
sh "sudo zfs rollback zpool0/${compiler}@latest"
throw e
}
}
}
}
def buildsMap = compilers.collectEntries {
["${it}": build(it)]
}
def build(compiler) {
return {
stage("Build: ${compiler}") {
try {
ws("/zpool0/${compiler}") {
docker.image("0ad-${compiler}:latest").inside {
sh "build/workspaces/update-workspaces.sh -j1 --jenkins-tests"
- // TODO: Mark build as unstable in case of warnings and tweak the plugin accordingly.
+ try {
+ retry(3) {
+ sh "cd build/workspaces/gcc/ && make -j1 config=debug 2> ../../../builderr-debug-${compiler}.txt"
+ }
+ } catch(e) {
+ throw e
+ } finally {
+ stash includes: "builderr-debug-${compiler}.txt", name: "build-debug-${compiler}"
+ }
- sh "cd build/workspaces/gcc/ && make -j1 config=debug"
try {
sh "binaries/system/test_dbg > cxxtest-debug-${compiler}.xml"
} catch (e) {
echo (message: readFile (file: "cxxtest-debug-${compiler}.xml"))
throw e
} finally {
stash includes: "cxxtest-debug-${compiler}.xml", name: "tests-debug-${compiler}"
}
- sh "cd build/workspaces/gcc/ && make -j1 config=release"
+ try {
+ retry(3) {
+ sh "cd build/workspaces/gcc/ && make -j1 config=release 2> ../../../builderr-release-${compiler}.txt"
+ }
+ } catch(e) {
+ throw e
+ } finally {
+ stash includes: "builderr-release-${compiler}.txt", name: "build-release-${compiler}"
+ }
+
try {
sh "binaries/system/test > cxxtest-release-${compiler}.xml"
} catch (e) {
echo (message: readFile (file: "cxxtest-release-${compiler}.xml"))
throw e
} finally {
stash includes: "cxxtest-release-${compiler}.xml", name: "tests-release-${compiler}"
}
}
}
} catch (e) {
throw e
} finally {
sh "sudo zfs rollback zpool0/${compiler}@latest"
}
}
}
}
pipeline {
agent {
node {
label 'LinuxSlave'
customWorkspace '/zpool0/trunk'
}
}
parameters {
string(name: 'DIFF_ID', defaultValue: '', description: 'ID of the Phabricator Differential.')
string(name: 'PHID', defaultValue: '', description: 'Phabricator ID')
}
stages {
stage("Patch") {
steps {
sh "arc patch --diff ${params.DIFF_ID} --force"
script { parallel patchesMap }
}
}
stage("Build") {
steps {
script { parallel buildsMap }
}
post {
always {
script {
for(compiler in compilers) {
+ catchError { unstash "build-debug-${compiler}" }
catchError { unstash "tests-debug-${compiler}" }
+ catchError { unstash "build-release-${compiler}" }
catchError { unstash "tests-release-${compiler}" }
}
}
+ catchError {
+ sh '''
+ for file in builderr-*.txt ; do
+ if [ -s "$file" ]; then
+ echo "$file" >> build-errors.txt
+ cat "$file" >> build-errors.txt
+ fi
+ done
+ '''
+ }
catchError { junit 'cxxtest*.xml' }
}
}
}
stage("Lint") {
steps {
script {
try {
withDockerContainer("0ad-coala:latest") {
- sh "svn st | grep '^[AM]' | cut -c 9- | xargs coala -d build/coala --ci --flush-cache --limit-files > coala-report"
+ sh '''
+ svn st | grep '^[AM]' | cut -c 9- | xargs coala -d build/coala --ci --disable-caching \
+ --format '{{ "name": "{origin}", "code": "{origin}", "severity": "{severity_str}", "path": "{file}", "line": {line}, "description": "`{message}`" }}' \
+ --limit-files > coala-report
+ '''
}
} catch (e) {
- sh '''
- echo "Linter detected issues:" >> phabricator-comment
- cat coala-report >> phabricator-comment
- echo "\n" >> phabricator-comment
- '''
+ sh 'sed -i "s|$(pwd)/||g" coala-report'
+ sh 'sed -e "s/INFO/advice/g" -e "s/NORMAL/warning/g" -e "s/MAJOR/error/g" coala-report > .phabricator-lint'
}
}
- echo (message: readFile (file: "coala-report"))
}
}
stage("Data checks") {
steps {
- sh "cd source/tools/entity/ && perl checkrefs.pl --check-map-xml --validate-templates"
+ sh "cd source/tools/entity/ && perl checkrefs.pl --check-map-xml --validate-templates 2> data-errors.txt"
}
}
}
post {
always {
script {
+ catchError {
+ sh "if [ -s build-errors.txt ]; then cat build-errors.txt >> .phabricator-comment ; fi"
+ sh '''
+ if [ -s data-errors.txt ]; then
+ echo "Data checks errors:" >> .phabricator-comment
+ cat data-errors.txt >> .phabricator-comment
+ fi
+ '''
+ }
+
try {
- if (fileExists("phabricator-comment")) {
- step([$class: 'PhabricatorNotifier', commentOnSuccess: true, commentWithConsoleLinkOnFailure: true, customComment: true, commentFile: "phabricator-comment"])
+ if (fileExists(".phabricator-comment")) {
+ step([$class: 'PhabricatorNotifier', commentOnSuccess: true, commentWithConsoleLinkOnFailure: true, customComment: true, commentFile: ".phabricator-comment", processLint: true, lintFile: ".phabricator-lint"])
} else {
- step([$class: 'PhabricatorNotifier', commentOnSuccess: true, commentWithConsoleLinkOnFailure: true])
+ step([$class: 'PhabricatorNotifier', commentWithConsoleLinkOnFailure: true, processLint: true, lintFile: ".phabricator-lint"])
}
} catch(e) {
throw e
} finally {
sh "sudo zfs rollback zpool0/trunk@latest"
}
}
}
}
}
Index: ps/trunk/build/jenkins/pipelines/macos-differential.Jenkinsfile
===================================================================
--- ps/trunk/build/jenkins/pipelines/macos-differential.Jenkinsfile (revision 23970)
+++ ps/trunk/build/jenkins/pipelines/macos-differential.Jenkinsfile (revision 23971)
@@ -1,111 +1,133 @@
/* Copyright (C) 2020 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
pipeline {
agent { label 'MacSlave' }
options {
skipDefaultCheckout()
}
parameters {
string(name: 'DIFF_ID', defaultValue: '', description: 'ID of the Phabricator Differential.')
string(name: 'PHID', defaultValue: '', description: 'Phabricator ID')
}
stages {
stage ("Checkout") {
options {
retry(3)
}
steps {
script {
try {
svn "https://svn.wildfiregames.com/public/ps/trunk"
} catch(e) {
sh "svn cleanup"
sleep 300
throw e
}
}
sh "svn cleanup"
}
}
stage ("Patch") {
steps {
script {
try {
sh "arc patch --diff ${params.DIFF_ID} --force"
} catch (e) {
sh "svn revert -R ."
sh "svn st | cut -c 9- | xargs rm -rf"
sh "arc patch --diff ${params.DIFF_ID} --force"
}
}
}
}
stage("macOS libraries build") {
steps {
sh "cd libraries/osx/ && ./build-osx-libs.sh -j4"
}
}
stage("Update workspaces") {
steps {
sh "cd build/workspaces/ && ./update-workspaces.sh -j4 --atlas --jenkins-tests"
}
}
stage("Debug Build & Tests") {
steps {
- sh "cd build/workspaces/gcc/ && make -j4 config=debug"
+ sh "cd build/workspaces/gcc/ && make -j4 config=debug 2> ../../../builderr-debug-macos.txt"
script {
try {
sh "binaries/system/test_dbg > cxxtest-debug.xml"
} catch (e) {
echo (message: readFile (file: "cxxtest-debug.xml"))
throw e
} finally {
junit "cxxtest-debug.xml"
}
}
}
}
stage("Release Build & Tests") {
steps {
- sh "cd build/workspaces/gcc/ && make -j4 config=release"
+ sh "cd build/workspaces/gcc/ && make -j4 config=release 2> ../../../builderr-release-macos.txt"
script {
try {
sh "binaries/system/test > cxxtest-release.xml"
} catch (e) {
echo (message: readFile (file: "cxxtest-release.xml"))
throw e
} finally {
junit "cxxtest-release.xml"
}
}
}
}
}
post {
always {
- step([$class: 'PhabricatorNotifier', commentOnSuccess: true, commentWithConsoleLinkOnFailure: true])
- sh "rm -f cxxtest_*.xml"
- sh "svn revert -R ."
- sh "svn st binaries/data/ | cut -c 9- | xargs rm -rf"
- sh "svn st source/ | cut -c 9- | xargs rm -rf"
+ script {
+ catchError {
+ sh '''
+ for file in builderr-*.txt ; do
+ if [ -s "$file" ]; then
+ echo "$file" >> .phabricator-comment
+ cat "$file" >> .phabricator-comment
+ fi
+ done
+ '''
+ }
+
+ try {
+ if (fileExists(".phabricator-comment")) {
+ step([$class: 'PhabricatorNotifier', commentOnSuccess: true, commentWithConsoleLinkOnFailure: true, customComment: true, commentFile: ".phabricator-comment"])
+ } else {
+ step([$class: 'PhabricatorNotifier', commentWithConsoleLinkOnFailure: true])
+ }
+ } catch(e) {
+ throw e
+ } finally {
+ sh "rm -f .phabricator-comment builderr-*.txt cxxtest_*.xml"
+ sh "svn revert -R ."
+ sh "svn st binaries/data/ | cut -c 9- | xargs rm -rf"
+ sh "svn st source/ | cut -c 9- | xargs rm -rf"
+ }
+ }
}
}
}