Skip to content

Commit

Permalink
[ant] Add Ant support. Fixes #43
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmiray committed Mar 20, 2021
1 parent c5630fa commit cd5ab43
Show file tree
Hide file tree
Showing 18 changed files with 446 additions and 23 deletions.
17 changes: 9 additions & 8 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,18 @@ snapcrafts:
confinement: classic
license: Apache-2.0
publish: true
summary: "Gum is a Gradle/Maven/jbang wrapper written in Go"
summary: "Gum is a Gradle/Maven/Ant/Bach/JBang wrapper written in Go"
description: |
Gum is a Gradle/Maven/jbang wrapper written in Go, inspired in https://github.com/dougborg/gdub and https://github.com/srs/gw.
Gum automatically detects if the project is Gradle, Maven, Bach, or jbang based and runs the appropriate command. However in the case
that Gum guesses wrong you can force a specific build tool to be used. Similarly as gdub, Gum lets you invoke either Gradle or
Maven from anywhere within the project structure, not just the root directory.
Gum is a Gradle/Maven/Ant/Bach/JBang wrapper written in Go, inspired in https://github.com/dougborg/gdub and https://github.com/srs/gw.
Gum automatically detects if the project is Gradle, Maven, Ant, Bach, or JBang based and runs the appropriate command. However
in the case that Gum guesses wrong you can force a specific build tool to be used. Similarly as gdub, Gum lets you invoke either
Gradle, Maven, or Ant from anywhere within the project structure, not just the root directory.
**Usage**
Gum supports the following flags
* **-ga** force Ant execution
* **-gb** force Bach execution
* **-gc** displays current configuration and quits
* **-gd** displays debug information
Expand All @@ -74,8 +75,8 @@ snapcrafts:
* **-gv** displays version information
Gum will execute the build based on the root build file unless **-gn** is specified, in which case the nearest build file
will be selected. If a specific build file is given (**-b**, **--build-file** for Gradle; **-f**, **--file** for Maven)
then that file will be used instead.
will be selected. If a specific build file is given (**-b**, **--build-file** for Gradle; **-f**, **--file** for Maven,
**-f**, **-file**, **-buildfile** for Ant) then that file will be used instead.
brews:
- name: gum
goarm: 6
Expand All @@ -84,6 +85,6 @@ brews:
name: gum-homebrew-tap
folder: Formula
homepage: "https://github.com/kordamp/gm"
description: "Gum is a Gradle/Maven/jbang wrapper written in Go"
description: "Gum is a Gradle/Maven/Ant/Bach/JBang wrapper written in Go"
license: Apache-2.0
skip_upload: false
17 changes: 9 additions & 8 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ image:https://img.shields.io/github/downloads/{project-owner}/{project-name}/tot

---

Gum is a link:https://gradle.org[Gradle]/link:https:maven.apache.org[Maven]/link:https://github.com/sormuras/bach/[Bach]/link:https://github.com/jbangdev[JBang]
wrapper written in link:https://golang.org/[Go], inspired in link:https://github.com/dougborg/gdub[https://github.com/dougborg/gdub] and
Gum is a link:https://gradle.org[Gradle]/link:https:maven.apache.org[Maven]/link:https://github.com/sormuras/bach/[Bach]/link:https://github.com/jbangdev[JBang]/link:https://ant.apache.org/[Ant] wrapper written in link:https://golang.org/[Go], inspired in link:https://github.com/dougborg/gdub[https://github.com/dougborg/gdub] and
link:https://github.com/srs/gw[https://github.com/srs/gw].

Gum automatically detects if the project is Gradle, Maven, Bach, or jbang based and runs the appropriate command. However in the case that Gum guesses wrong
you canforce a specific build tool to be used. Similarly as gdub, Gum lets you invoke either Gradle or Maven from anywhere within the project structure,
not just the root directory.
Gum automatically detects if the project is Gradle, Maven, Bach, JBang or Ant based and runs the appropriate command.
However in the case that Gum guesses wrong you canforce a specific build tool to be used. Similarly as gdub, Gum lets
you invoke either Gradle, Maven, or Ant from anywhere within the project structure, not just the root directory.

== Usage

Gum supports the following flags

* *-ga* force Ant execution
* *-gb* force Bach execution
* *-gc* displays current configuration and quits
* *-gd* displays debug information
Expand All @@ -36,8 +36,9 @@ Gum supports the following flags
* *-gr* do not replace goals/tasks
* *-gv* displays version information

Gum will execute the build based on the root build file unless *-gn* is specified, in which case the nearest build file will be selected.
If a specific build file is given (*-b*, *--build-file* for Gradle; *-f*, *--file* for Maven) then that file will be used instead.
Gum will execute the build based on the root build file unless *-gn* is specified, in which case the nearest build file
will be selected. If a specific build file is given (*-b*, *--build-file* for Gradle; *-f*, *--file* for Maven, *-f*,
*-file*, *-buildfile* for Ant) then that file will be used instead.

Gum works by passing the given arguments to the resolved tool; it will replace common goal/task names following these mappings

Expand Down Expand Up @@ -119,7 +120,7 @@ quiet = false
debug = false
# tool discovery order
# default order is the following
discovery = ["gradle", "maven", "bach", "jbang"]
discovery = ["gradle", "maven", "ant", "bach", "jbang"]
[gradle]
# if goal/tasks should be replaced, same as passing -gr
Expand Down
9 changes: 8 additions & 1 deletion gm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func main() {
gradleBuild := args.HasGumFlag("gg")
mavenBuild := args.HasGumFlag("gm")
jbangBuild := args.HasGumFlag("gj")
antBuild := args.HasGumFlag("ga")
version := args.HasGumFlag("gv")
help := args.HasGumFlag("gh")

Expand All @@ -49,6 +50,7 @@ func main() {

if help {
fmt.Println("Usage of gm:")
fmt.Println(" -ga\tforce Ant build")
fmt.Println(" -gb\tforce Bach build")
fmt.Println(" -gc\tdisplays current configuration and quits")
fmt.Println(" -gd\tdisplays debug information")
Expand Down Expand Up @@ -76,9 +78,12 @@ func main() {
if bachBuild {
count = count + 1
}
if antBuild {
count = count + 1
}

if count > 1 {
fmt.Println("You cannot define -gb, -gg, -gm, or -gj flags at the same time")
fmt.Println("You cannot define -gb, -gg, -gm, gj, or -ga flags at the same time")
os.Exit(-1)
}

Expand All @@ -90,6 +95,8 @@ func main() {
gum.FindJbang(gum.NewDefaultContext(true), &args).Execute()
} else if bachBuild {
gum.FindBach(gum.NewDefaultContext(true), &args).Execute()
} else if antBuild {
gum.FindAnt(gum.NewDefaultContext(true), &args).Execute()
} else {
gum.FindTool(&args)
}
Expand Down
237 changes: 237 additions & 0 deletions gum/ant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2020-2021 Andres Almiray.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gum

import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)

// AntCommand defines an executable Ant command
type AntCommand struct {
context Context
config *Config
rootdir string
executable string
args *ParsedArgs
buildFile string
explicitBuildFile string
}

// Execute executes the given command
func (c AntCommand) Execute() {
c.doConfigureAnt()
c.doExecuteAnt()
}

func (c *AntCommand) doConfigureAnt() {
args := make([]string, 0)

banner := make([]string, 0)
banner = append(banner, "Using Ant at '"+c.executable+"'")

debug := c.args.HasGumFlag("gd")

if debug {
c.config.setDebug(debug)
}
c.debugConfig()
oargs := c.args.Args

if len(c.explicitBuildFile) > 0 {
args = append(args, "-f")
args = append(args, c.explicitBuildFile)
banner = append(banner, "to run buildFile '"+c.explicitBuildFile+"':")
} else if len(c.buildFile) > 0 {
args = append(args, "-f")
args = append(args, c.buildFile)
banner = append(banner, "to run buildFile '"+c.buildFile+"':")
}

args = appendSafe(args, c.args.Tool)
args = append(args, "-Dbasedir="+c.rootdir)
c.args.Args = appendSafe(args, oargs)

c.debugAnt(c.config, oargs)

if !c.config.general.quiet {
fmt.Println(strings.Join(banner, " "))
}
}

func (c *AntCommand) doExecuteAnt() {
cmd := exec.Command(c.executable, c.args.Args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
}

func (c *AntCommand) debugConfig() {
if c.args.HasGumFlag("gc") {
c.config.print()
os.Exit(0)
}
}

func (c *AntCommand) debugAnt(config *Config, oargs []string) {
if c.config.general.debug {
fmt.Println("rootdir = ", c.rootdir)
fmt.Println("executable = ", c.executable)
fmt.Println("buildFile = ", c.buildFile)
fmt.Println("explicitBuildFile = ", c.explicitBuildFile)
fmt.Println("original args = ", oargs)
fmt.Println("actual args = ", c.args.Args)
fmt.Println("")
}
}

// FindAnt finds and executes Ant
func FindAnt(context Context, args *ParsedArgs) *AntCommand {
pwd := context.GetWorkingDir()

ant, noAnt := findAntExec(context)
explicitBuildFileSet, explicitBuildFile := findExplicitAntBuildFile(args)
buildFile, noBuildFile := findAntBuildFile(context, pwd)

rootdir := resolveAntRootDir(context, explicitBuildFile, buildFile)
config := ReadConfig(context, rootdir)
quiet := args.HasGumFlag("gq")

if quiet {
config.setQuiet(quiet)
}

var executable string
if noAnt == nil {
executable = ant
} else {
warnNoAnt(context, config)

if context.IsExplicit() {
context.Exit(-1)
}
return nil
}

if explicitBuildFileSet {
return &AntCommand{
context: context,
config: config,
executable: executable,
args: args,
explicitBuildFile: explicitBuildFile}
}

if noBuildFile != nil {
if context.IsExplicit() {
fmt.Println("No Ant project found")
fmt.Println()
context.Exit(-1)
}
return nil
}

return &AntCommand{
context: context,
config: config,
rootdir: rootdir,
executable: executable,
args: args,
buildFile: buildFile}
}

func resolveAntRootDir(context Context,
explicitBuildFile string,
buildFile string) string {

if context.FileExists(explicitBuildFile) {
return filepath.Dir(explicitBuildFile)
}
return filepath.Dir(buildFile)
}

func warnNoAnt(context Context, config *Config) {
if !config.general.quiet && context.IsExplicit() {
fmt.Printf("No %s found in path. Please install Ant.", resolveAntExec(context))
fmt.Println()
fmt.Println("(https://ant.apache.org/bindownload.cgi)")
fmt.Println()
}
}

// Finds the ant executable
func findAntExec(context Context) (string, error) {
ant := resolveAntExec(context)
paths := context.GetPaths()

for i := range paths {
name := filepath.Join(paths[i], ant)
if context.FileExists(name) {
return filepath.Abs(name)
}
}

return "", errors.New(ant + " not found")
}

func findExplicitAntBuildFile(args *ParsedArgs) (bool, string) {
found, file, shrunkArgs := findFlagValue("-f", args.Tool)
args.Tool = shrunkArgs
if !found {
found, file, shrunkArgs = findFlagValue("-file", args.Tool)
args.Tool = shrunkArgs
}
if !found {
found, file, shrunkArgs = findFlagValue("-buildfile", args.Tool)
args.Tool = shrunkArgs
}

if found {
file, _ = filepath.Abs(file)
return true, file
}

return false, ""
}

// Finds the nearest build.xml
func findAntBuildFile(context Context, dir string) (string, error) {
parentdir := filepath.Join(dir, "..")

if parentdir == dir {
return "", errors.New("Did not find build.xml")
}

path := filepath.Join(dir, "build.xml")
if context.FileExists(path) {
return filepath.Abs(path)
}

return findAntBuildFile(context, parentdir)
}

// Resolves the ant executable (OS dependent)
func resolveAntExec(context Context) string {
if context.IsWindows() {
return "ant.bat"
}
return "ant"
}
Loading

0 comments on commit cd5ab43

Please sign in to comment.