예제 #1
0
// remove path String > err String
// """
//  Removes the named file or directory.
// """
//
func remove(th InterpreterThread, objects []RObject) []RObject {

	path := string(objects[0].(String))

	err := gos.Remove(path)
	errStr := ""
	if err != nil {
		errStr = err.Error()
	}
	return []RObject{String(errStr)}
}
/*
Remove the existing shared copy of the version of the artifact (in a failsafe manner).
Copy source code for the version of the package to the shared sourcecode tree.
Create a zip file of the version of the artifact.
Wrap that with another zip file which will eventually contain a certificate
of the origin's public key, and a signature of (the SHA256 hash of) the inner zip file contents.
Name the outer zip file by an unambiguous name corresponding to the version of the artifact from the origin.
Check to see if there is a metadata file in the shared directory for the artifact.
If no metadata file in shared, add it. Metadata file name should again be fully qualified unambiguous name,
to ensure findability by Google search. Or the content should contain a standard findable title like
"Relish Artifact Metadata".
Note that the metadata.txt file should eventually also include,
below its meaningful text content, a certificate of the origin's public key, and a signature of (the SHA256 hash of)
the meaningful content.
Should copy local artifact version directory tree that was published to create the next version to continue work on.

Note about signed code plans
============================
The plan is to have every copy of relish include the public key of shared.relish.pl.
This key can be directly compared manually at any time with the public key published at the site shared.relish.pl.

Each code-origin owner who wants to officially publish relish code should register their origin at shared.relish.pl
and should receive back both
1) a certificate (signed by shared.relish.pl and verifiable with shared.relish.pl's public key)
   where such certificate attests to the association between another public key and the origin name.
2) The actual origin public key
3) A corresponding private key.

The origin owner should keep their private key secret but install it in a standard place
within their relish development environment so that their relish instance can use it to sign code.

The origin owner should also keep their certificate of their public key installed at a standard place
in their relish development environment, so they can include that cert in signed-code outer zip files.
The certified public key should actually be published at a standard place in the canonical server
for the origin, and also at shared.relish.pl. This is so that such a key can periodically be verified
as being a currently valid one.

Note: If the private key is stolen, someone else can produce code signed as coming from your origin,
so maybe the same password used to sign up to register your origin should serve as a decryption key
for a symmetrically encrypted version of the private key. So you would be prompted to enter the password
when publishing (and signing) some code.

If not using encrypted private key, then if it is discovered that the key has been stolen (e.g. some code
fraudulently claiming to be from the origin is discovered), then a solution would be to apply for a
new public key for the origin, and re-publish all legitimate code signed by the new key.

Periodically, a imported-code-using instance of relish should re-verify (at the canonical server or shared.relish.pl)
that the public key that is signing each of their imported artifacts is still the valid public key for the origin.

Perhaps shared.relish.pl can contain a timestamp of when the most recent re-keying incident happened,
and relish instances can periodically check that to see if re-verification of origin public-keys, and
possible redownloading of re-signed code artifacts is necessary.

*/
func PublishSourceCode(relishRoot string, originAndArtifact string, version string) (err error) {

	slashPos := strings.Index(originAndArtifact, "/")
	originId := originAndArtifact[:slashPos]

	// Obtain the private key for the origin that is publishing.

	originPrivateKey, err := crypto_util.GetPrivateKey("origin", originId)
	if err != nil {
		return
	}

	// Obtain the public key certificate for the origin that is publishing.

	originPublicKeyCertificate, err := crypto_util.GetPublicKeyCert("origin", originId)
	if err != nil {
		return
	}

	// Obtain the public key certificate of shared.relish.pl2012

	sharedRelishPublicKeyCertificate, err := crypto_util.GetPublicKeyCert("origin", "shared.relish.pl2012")
	if err != nil {
		return
	}

	// Validate that it is signed properly, obtaining the shared.relish.pl2012 publicKeyPEM.

	sharedRelishPublicKey := crypto_util.VerifiedPublicKey("", sharedRelishPublicKeyCertificate, "origin", "shared.relish.pl2012")

	if sharedRelishPublicKey == "" {
		err = errors.New("Invalid shared.relish.pl2012 public key certificate.")
		return
	}

	// Do a quick validation of publishing origin's public key cert

	originPublicKey := crypto_util.VerifiedPublicKey(sharedRelishPublicKey, originPublicKeyCertificate, "origin", originId)

	if originPublicKey == "" {
		err = errors.New("Invalid " + originId + " public key certificate.")
		return
	}

	// prompt for the publishing origin's private key password.

	var buf *bufio.Reader = bufio.NewReader(os.Stdin)
	fmt.Print("Enter code-origin administration password:"******"/artifacts/" + originAndArtifact + "/"
	sharedArtifactPath := relishRoot + "/shared/relish/artifacts/" + originAndArtifact + "/"

	// Check if metadata.txt file exists in shared. If not, create it by copying local metadata.txt file

	sharedMetadataPath := sharedArtifactPath + "metadata.txt"
	_, err = gos.Stat(sharedMetadataPath)
	if err != nil {
		if os.IsNotExist(err) {

			err = gos.MkdirAll(sharedArtifactPath, 0777)
			if err != nil {
				fmt.Printf("Error making shared artifact directory %s: %s\n", sharedArtifactPath, err)
				return
			}

			localMetadataPath := localArtifactPath + "metadata.txt"
			var content []byte
			content, err = gos.ReadFile(localMetadataPath)
			if err != nil {
				return
			}
			err = gos.WriteFile(sharedMetadataPath, content, 0666)
			if err != nil {
				return
			}
		} else {
			fmt.Printf("Can't stat  '%s' : %v\n", sharedArtifactPath+"metadata.txt", err)
			return
		}
	}

	// Note. This does not update the shared metadata.txt file from the local if the shared metadata.txt
	// file already existed.

	//

	versionPath := "v" + version

	sharedArtifactVersionPath := sharedArtifactPath + versionPath

	_, err = gos.Stat(sharedArtifactVersionPath)
	foundVersionShared := false
	if err != nil {
		if !os.IsNotExist(err) {
			fmt.Printf("Can't stat directory '%s' : %v\n", sharedArtifactVersionPath, err)
			return
		}
	} else {
		foundVersionShared = true
	}
	if foundVersionShared {
		fmt.Printf("%s already exists. Cannot republish the same version.\n", sharedArtifactVersionPath)
		return
	}

	localSrcDirPath := localArtifactPath + versionPath + "/src"
	srcDirPath := sharedArtifactVersionPath + "/src"
	localDocDirPath := localArtifactPath + versionPath + "/doc"
	docDirPath := sharedArtifactVersionPath + "/doc"

	// mkdir the version of the shared directory

	err = gos.MkdirAll(sharedArtifactVersionPath, 0777)

	if err != nil {
		fmt.Printf("Error making shared artifact version directory %s: %s\n", sharedArtifactVersionPath, err)
		return
	}

	// Copy source code directory tree to "shared/relish/artifacts" tree root.

	err = copySrcDirTree(localSrcDirPath, srcDirPath)
	if err != nil {
		fmt.Printf("Error copying local src dir to create %s: %s\n", srcDirPath, err)
		return
	}

	_, statErr := gos.Stat(localDocDirPath)
	if statErr == nil {
		err = copyDocDirTree(localDocDirPath, docDirPath)
		if err != nil {
			fmt.Printf("Error copying local doc dir to create %s: %s\n", docDirPath, err)
			return
		}
	}
	// TBD

	// Zip the source and docs!

	srcZipFilePath := sharedArtifactVersionPath + "/artifactVersionContents.zip"
	err = zipSrcAndDocDirTrees(srcDirPath, docDirPath, srcZipFilePath)
	if err != nil {
		fmt.Printf("Error zipping %s and %s: %s\n", srcDirPath, docDirPath, err)
		return
	}

	// Now have to sign it and put into an outer zip file.

	err = signZippedSrc(srcZipFilePath, originPrivateKey, originPrivateKeyPassword, originPublicKeyCertificate, sharedRelishPublicKeyCertificate, sharedArtifactPath, originAndArtifact, version)
	if err != nil {
		fmt.Printf("Error signing %s: %s\n", srcZipFilePath, err)
		return
	}

	err = gos.Remove(srcZipFilePath)
	if err != nil {
		fmt.Printf("Error removing %s: %s\n", srcZipFilePath, err)
		return
	}
	return
}