Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/lsif_transformer/parser/parser.go')
-rw-r--r--workhorse/internal/lsif_transformer/parser/parser.go109
1 files changed, 109 insertions, 0 deletions
diff --git a/workhorse/internal/lsif_transformer/parser/parser.go b/workhorse/internal/lsif_transformer/parser/parser.go
new file mode 100644
index 00000000000..085e7a856aa
--- /dev/null
+++ b/workhorse/internal/lsif_transformer/parser/parser.go
@@ -0,0 +1,109 @@
+package parser
+
+import (
+ "archive/zip"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+
+ "gitlab.com/gitlab-org/labkit/log"
+)
+
+var (
+ Lsif = "lsif"
+)
+
+type Parser struct {
+ Docs *Docs
+
+ pr *io.PipeReader
+}
+
+type Config struct {
+ TempPath string
+}
+
+func NewParser(ctx context.Context, r io.Reader, config Config) (io.ReadCloser, error) {
+ docs, err := NewDocs(config)
+ if err != nil {
+ return nil, err
+ }
+
+ // ZIP files need to be seekable. Don't hold it all in RAM, use a tempfile
+ tempFile, err := ioutil.TempFile(config.TempPath, Lsif)
+ if err != nil {
+ return nil, err
+ }
+
+ defer tempFile.Close()
+
+ if err := os.Remove(tempFile.Name()); err != nil {
+ return nil, err
+ }
+
+ size, err := io.Copy(tempFile, r)
+ if err != nil {
+ return nil, err
+ }
+ log.WithContextFields(ctx, log.Fields{"lsif_zip_cache_bytes": size}).Print("cached incoming LSIF zip on disk")
+
+ zr, err := zip.NewReader(tempFile, size)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(zr.File) == 0 {
+ return nil, errors.New("empty zip file")
+ }
+
+ file, err := zr.File[0].Open()
+ if err != nil {
+ return nil, err
+ }
+
+ defer file.Close()
+
+ if err := docs.Parse(file); err != nil {
+ return nil, err
+ }
+
+ pr, pw := io.Pipe()
+ parser := &Parser{
+ Docs: docs,
+ pr: pr,
+ }
+
+ go parser.transform(pw)
+
+ return parser, nil
+}
+
+func (p *Parser) Read(b []byte) (int, error) {
+ return p.pr.Read(b)
+}
+
+func (p *Parser) Close() error {
+ p.pr.Close()
+
+ return p.Docs.Close()
+}
+
+func (p *Parser) transform(pw *io.PipeWriter) {
+ zw := zip.NewWriter(pw)
+
+ if err := p.Docs.SerializeEntries(zw); err != nil {
+ zw.Close() // Free underlying resources only
+ pw.CloseWithError(fmt.Errorf("lsif parser: Docs.SerializeEntries: %v", err))
+ return
+ }
+
+ if err := zw.Close(); err != nil {
+ pw.CloseWithError(fmt.Errorf("lsif parser: ZipWriter.Close: %v", err))
+ return
+ }
+
+ pw.Close()
+}