[attrs] Make jiri output a JSON for optional attributes.

This change adds a new feature to Jiri to generate a JSON file
containing optional attributes when Jiri fetch packages.

Bug: 41045
Change-Id: I31358a725b11f4231be5406440353919748291e0
diff --git a/project/manifest.go b/project/manifest.go
index be40f99..ddc51ab 100644
--- a/project/manifest.go
+++ b/project/manifest.go
@@ -912,7 +912,7 @@
 			jirix.Logger.Warningf("Some packages are skipped by cipd due to lack of access, you might want to run \"%s auth-login\" and try again", jirix.CIPDPath())
 		}
 	}
-	return nil
+	return writeAttributesJSON(jirix)
 }
 
 // WritePackageFlags write flag files into project directory using in "flag"
diff --git a/project/project.go b/project/project.go
index f5015d8..0486f3b 100644
--- a/project/project.go
+++ b/project/project.go
@@ -2439,3 +2439,20 @@
 	metadataFile := filepath.Join(metadataDir, jiri.ProjectMetaFile)
 	return project.ToFile(jirix, metadataFile)
 }
+
+func writeAttributesJSON(jirix *jiri.X) error {
+	attrs := make([]string, 0)
+	for k := range newAttributes(jirix.FetchingAttrs) {
+		attrs = append(attrs, k)
+	}
+	jsonData, err := json.MarshalIndent(&attrs, "", "    ")
+	if err != nil {
+		return err
+	}
+	jsonFile := filepath.Join(jirix.RootMetaDir(), jiri.AttrsJSON)
+	if err := safeWriteFile(jirix, jsonFile, jsonData); err != nil {
+		return err
+	}
+	jirix.Logger.Debugf("package optional attributes written to %s", jsonFile)
+	return nil
+}
diff --git a/x.go b/x.go
index 842c567..96ba94d 100644
--- a/x.go
+++ b/x.go
@@ -30,6 +30,7 @@
 )
 
 const (
+	AttrsJSON          = "attributes.json"
 	RootMetaDir        = ".jiri_root"
 	ProjectMetaDir     = ".git/jiri"
 	OldProjectMetaDir  = ".jiri"