Spracherkennung für: .go vermutete Sprache: Abap {ABAP[81] Cobol[42] C[30]} [Methode: maximale Elemente, drei Dimensionen]
// Copyright
2019 Google Inc. All rights reserved.
//
// 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
//
//
http://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 main
import (
"archive/zip"
"context"
"fmt"
"hash/crc32"
"io"
"io/ioutil"
"os"
"path/filepath"
)
// ZipArtifact represents a zip
file that may be
local or remote.
type ZipArtifact
interface {
// Files returns the list
of files contained
in the zip
file.
Files() ([]
*ZipArtifactFile, error)
//
Close closes the zip
file artifact.
Close()
}
// localZipArtifact
is a handle
to a
local zip
file artifact.
type localZipArtifact struct {
zr
*zip.ReadCloser
files []
*ZipArtifactFile
}
// NewLocalZipArtifact returns a ZipArtifact
for a
local zip
file..
func NewLocalZipArtifact(name
string) (ZipArtifact, error) {
zr, err := zip.OpenReader(name)
if err != nil {
return nil, err
}
var files []
*ZipArtifactFile
for _, zf := range zr.
File {
files =
append(files, &ZipArtifactFile{zf})
}
return &localZipArtifact{
zr: zr,
files: files,
}, nil
}
// Files returns the list
of files contained
in the
local zip
file artifact.
func (z
*localZipArtifact) Files() ([]*ZipArtifactFile, error) {
return z.files, nil
}
//
Close closes the buffered reader
of the
local zip
file artifact.
func (z
*localZipArtifact) Close() {
z.zr.
Close()
}
// ZipArtifactFile contains a zip.
File handle
to the
data inside the remote
*-target_files-*.zip
// build artifact.
type ZipArtifactFile struct {
*zip.File
}
//
Extract begins
extract a
file from inside a ZipArtifact. It returns an
// ExtractedZipArtifactFile handle.
func (zf
*ZipArtifactFile) Extract(ctx context.Context, dir string,
limiter chan bool)
*ExtractedZipArtifactFile {
d := &ExtractedZipArtifactFile{
initCh: make(chan struct{}),
}
go func() {
defer
close(d.initCh)
limiter <- true
defer func() { <-limiter }()
zr, err := zf.
Open()
if err != nil {
d.err = err
return
}
defer zr.
Close()
crc := crc32.NewIEEE()
r := io.TeeReader(zr, crc)
if filepath.Clean(zf.Name) != zf.Name {
d.err = fmt.Errorf(
"invalid filename %q", zf.Name)
return
}
path := filepath.
Join(dir, zf.Name)
err = os.MkdirAll(filepath.Dir(path),
0777)
if err != nil {
d.err = err
return
}
err = os.Remove(path)
if err != nil && !os.IsNotExist(err) {
d.err = err
return
}
if zf.Mode().IsRegular() {
w, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, zf.Mode())
if err != nil {
d.err = err
return
}
defer w.
Close()
_, err = io.
Copy(w, r)
if err != nil {
d.err = err
return
}
}
else if zf.Mode()&os.ModeSymlink !=
0 {
target, err := ioutil.ReadAll(r)
if err != nil {
d.err = err
return
}
err = os.Symlink(
string(target), path)
if err != nil {
d.err = err
return
}
}
else {
d.err = fmt.Errorf(
"unknown mode %q", zf.Mode())
return
}
if crc.Sum32() != zf.CRC32 {
d.err = fmt.Errorf(
"crc mismatch for %v", zf.Name)
return
}
d.path = path
}()
return d
}
// ExtractedZipArtifactFile
is a handle
to a downloaded
file from a remoteZipArtifact. The do
wnload
// may still be in progress, and will be complete with Path() returns.
type ExtractedZipArtifactFile struct {
initCh chan struct{}
err error
path string
}
// Path returns the path to the downloaded file and any errors that occurred during the download.
// It will block until the download is complete.
func (d *ExtractedZipArtifactFile) Path() (string, error) {
<-d.initCh
return d.path, d.err
}