Fantom

 

//
// Copyright (c) 2011, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//    23 Jun 11  Brian Frank  Creation
//

**
** UninstallCmd uninstalls a pod from the local environment
** with safety checks for dependencies.
**
internal class UninstallCmd : Command
{

//////////////////////////////////////////////////////////////////////////
// Usage
//////////////////////////////////////////////////////////////////////////

  override Str name() { "uninstall" }

  override Str summary() { "uninstall a pod from local env" }

//////////////////////////////////////////////////////////////////////////
// Args/Opts
//////////////////////////////////////////////////////////////////////////

  @CommandArg
  {
    name = "query"
    help = "query filter for pods to uninstall"
  }
  Str? query

//////////////////////////////////////////////////////////////////////////
// Execution
//////////////////////////////////////////////////////////////////////////

  override Void run()
  {
    // perform query
    specs := env.query(query)

    // handle no pods found
    if (specs.isEmpty)
    {
      out.printLine("No pods found")
      return
    }

    // format to output
    out.printLine
    specs.sort.each |spec|
    {
      printPodVersion(spec)
    }

    // ensure uninstall won't break any depends
    out.printLine
    if (!checkDepends(specs))
    {
      out.printLine
      out.printLine("Cannot uninstall without breaking above dependencies")
      return
    }

    // confirm
    msg := specs.size == 1 ?
      "Uninstall $specs.first.name?" :
      "Uninstall $specs.size pods?"
    if (!confirm(msg)) return

    // nuke each spec
    out.printLine
    specs.each |spec| { delete(spec) }
    out.printLine
    out.printLine("Uninstall successful ($specs.size pods)")
  }

  private Bool checkDepends(PodSpec[] specs)
  {
    // map specs by name
    map := Str:PodSpec[:].setList(specs) |s| { s.name }

    // walk thru all install pods not in our spec list
    ok := true
    env.queryAll.each |pod|
    {
      // if this pod in our uninstall list, then skip it
      if (map[pod.name] != null) return

      // we are keeping this guy, so make sure that none
      // of the pods to uninstall are in its depend list
      pod.depends.each |d|
      {
        if (map[d.name] != null)
        {
          out.printLine("ERROR: '$pod.name' depends on '$d.name'")
          ok = false
        }
      }
    }

    return ok
  }

  private Void delete(PodSpec spec)
  {
    file := Env.cur.findPodFile(spec.name)
    out.print("Deleting $file.osPath ... ").flush
    file.delete
    out.printLine("Complete")
  }

}