Каков наиболее подходящий способ повторного использования задачи Exec в gradle для общих операций с командной строкой?

Я пишу файл сборки gradle, который установит базовый домен разработки для нашего продукта. По сути, весь настоящий код будет в пользовательских плагинах и пользовательских задачах. Несколько из этих шагов являются довольно повторяющимися (несколько вызовов sudo, несколько пользовательских добавлений), и я хотел бы инкапсулировать общий материал в задачу.

Например:

task('addDBUser', type:AddUser) {
    username = joeUser
}

task('startService', type:SudoExec) {
    workingDir = "not/too/relevant"
    commandLine = "/etc/init.d/coolService start"
}

Я хотел бы повторно использовать различные функциональные возможности, которые Exec получает от меня (stdin, stdout и т.д.) как можно более аккуратно, при этом автоматически поставляя шаблон ( "sudo..." ). Я почти уверен, что могу просто расширить Exec вместо DefaultTask, но я не знаю стандартного способа запуска фактического действия. Кажется, легко изменить свойство commandLine с тем, что мне нужно, но нет никакого общего "run()" или тому подобного для использования, когда я хочу, чтобы Exec действительно ушел.

Я открываю Exec, чтобы определить, какой метод это метод работы, а затем вызвать его напрямую? Или существует более общий способ достижения моей цели?

Ответ 1

Чтобы узнать, какой метод выполняется для задачи, вы можете проверить источники Exec и выполнить поиск по методу, отмеченному @TaskAction. Оказывается, это метод exec(), но в общем случае вы не хотите вручную запускать действия с задачами, но пусть Gradle сделает это за вас. Лучшей идеей, на мой взгляд, является добавление методов/настроек в ваши пользовательские задачи. Это может выглядеть так:

task addUser(type: AddUser) {
    username = 'fromGradle'
}


class SudoExec extends Exec {

    void sudoCommand(Object... arguments) {
        executable 'sudo'
        args = arguments.toList()
    }
}

class AddUser extends SudoExec {

    void setUsername(String username) {
        sudoCommand('useradd', username)
    }
}

Ответ 2

Этот код способен обрабатывать несколько параметров, поскольку он не подключается к сеттерам любых конкретных параметров, но использует ленивую оценку GString.

task vagrantfile (type:Vagrantfile) {
    account 'vagrant'
    password 'vagrant'
}

class Vagrantfile extends Copy {
    String account
    String password

    def Vagrantfile() {
        from 'templates/'
        into 'build/'
        include 'Vagrantfile.ubuntu.tpl'
        rename {'Vagrantfile'}
        expand (account:"${->account}", password:"${->password}")
    }
}