blob: 5023a6c67c0d2a71f78dba3fe2ce3bc1d3726b0a [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"encoding/xml"
"fmt"
"os"
"fuchsia.googlesource.com/jiri"
"fuchsia.googlesource.com/jiri/cmdline"
"fuchsia.googlesource.com/jiri/project"
)
var (
// Flags for configuring project attributes for remote imports.
flagImportName, flagImportRemoteBranch, flagImportRoot string
// Flags for controlling the behavior of the command.
flagImportOverwrite bool
flagImportOut string
flagImportDelete bool
)
func init() {
cmdImport.Flags.StringVar(&flagImportName, "name", "manifest", `The name of the remote manifest project.`)
cmdImport.Flags.StringVar(&flagImportRemoteBranch, "remote-branch", "master", `The branch of the remote manifest project to track, without the leading "origin/".`)
cmdImport.Flags.StringVar(&flagImportRoot, "root", "", `Root to store the manifest project locally.`)
cmdImport.Flags.BoolVar(&flagImportOverwrite, "overwrite", false, `Write a new .jiri_manifest file with the given specification. If it already exists, the existing content will be ignored and the file will be overwritten.`)
cmdImport.Flags.StringVar(&flagImportOut, "out", "", `The output file. Uses <root>/.jiri_manifest if unspecified. Uses stdout if set to "-".`)
cmdImport.Flags.BoolVar(&flagImportDelete, "delete", false, `Delete existing import. Import is matched using <manifest>, <remote> and name. <remote> is optional.`)
}
var cmdImport = &cmdline.Command{
Runner: jiri.RunnerFunc(runImport),
Name: "import",
Short: "Adds imports to .jiri_manifest file",
Long: `
Command "import" adds imports to the [root]/.jiri_manifest file, which specifies
manifest information for the jiri tool. The file is created if it doesn't
already exist, otherwise additional imports are added to the existing file.
An <import> element is added to the manifest representing a remote manifest
import. The manifest file path is relative to the root directory of the remote
import repository.
Example:
$ jiri import myfile https://foo.com/bar.git
Run "jiri help manifest" for details on manifests.
`,
ArgsName: "<manifest> <remote>",
ArgsLong: `
<manifest> specifies the manifest file to use.
<remote> specifies the remote manifest repository.
`,
}
func isFile(file string) (bool, error) {
fileInfo, err := os.Stat(file)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return !fileInfo.IsDir(), nil
}
func runImport(jirix *jiri.X, args []string) error {
if flagImportDelete && len(args) != 1 && len(args) != 2 {
return jirix.UsageErrorf("wrong number of arguments with delete flag")
} else if !flagImportDelete && len(args) != 2 {
return jirix.UsageErrorf("wrong number of arguments")
}
if flagImportDelete && flagImportOverwrite {
return jirix.UsageErrorf("cannot use -delete and -overwrite together")
}
// Initialize manifest.
var manifest *project.Manifest
manifestExists, err := isFile(jirix.JiriManifestFile())
if err != nil {
return err
}
if !flagImportOverwrite && manifestExists {
m, err := project.ManifestFromFile(jirix, jirix.JiriManifestFile())
if err != nil {
return err
}
manifest = m
}
if manifest == nil {
manifest = &project.Manifest{}
}
if flagImportDelete {
var tempImports []project.Import
deletedImports := make(map[string]project.Import)
for _, imp := range manifest.Imports {
if imp.Manifest == args[0] && imp.Name == flagImportName {
match := true
if len(args) == 2 {
match = false
if imp.Remote == args[1] {
match = true
}
}
if match {
deletedImports[imp.Name+"~"+imp.Manifest+"~"+imp.Remote] = imp
continue
}
}
tempImports = append(tempImports, imp)
}
if len(deletedImports) > 1 {
return fmt.Errorf("More than 1 import meets your criteria. Please provide remote.")
} else if len(deletedImports) == 1 {
var data []byte
for _, i := range deletedImports {
data, err = xml.Marshal(i)
if err != nil {
return err
}
break
}
jirix.Logger.Infof("Deleted one import:\n%s", string(data))
}
manifest.Imports = tempImports
} else {
for _, imp := range manifest.Imports {
if imp.Manifest == args[0] && imp.Remote == args[1] && imp.Name == flagImportName {
//Already exists, skip
jirix.Logger.Debugf("Skip import. Duplicate entry")
return nil
}
}
// There's not much error checking when writing the .jiri_manifest file;
// errors will be reported when "jiri update" is run.
manifest.Imports = append(manifest.Imports, project.Import{
Manifest: args[0],
Name: flagImportName,
Remote: args[1],
RemoteBranch: flagImportRemoteBranch,
Root: flagImportRoot,
})
}
// Write output to stdout or file.
outFile := flagImportOut
if outFile == "" {
outFile = jirix.JiriManifestFile()
}
if outFile == "-" {
bytes, err := manifest.ToBytes()
if err != nil {
return err
}
_, err = os.Stdout.Write(bytes)
return err
}
return manifest.ToFile(jirix, outFile)
}