133 lines
4.0 KiB
Go
133 lines
4.0 KiB
Go
package golang
|
|
|
|
import (
|
|
// stdlib
|
|
"bytes"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
// local
|
|
"go.dev.pztrn.name/glp/configuration"
|
|
"go.dev.pztrn.name/glp/httpclient"
|
|
"go.dev.pztrn.name/glp/structs"
|
|
)
|
|
|
|
// Gets go-import and go-source data and fill it in dependency.
|
|
func getGoData(dependency *structs.Dependency) {
|
|
// Dependencies are imported using URL which can be called with
|
|
// "?go-get=1" parameter to obtain required VCS data.
|
|
req, _ := http.NewRequest("GET", "http://"+dependency.Name, nil)
|
|
|
|
q := req.URL.Query()
|
|
q.Add("go-get", "1")
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
respBody := httpclient.GET(req)
|
|
if respBody == nil {
|
|
return
|
|
}
|
|
|
|
// HTML is hard to parse properly statically, so we will go
|
|
// line-by-line for <head> parsing.
|
|
resp := bytes.NewBuffer(respBody)
|
|
|
|
var (
|
|
// This flag shows that we're currently parsing <head> from HTML.
|
|
headCurrentlyParsing bool
|
|
)
|
|
|
|
for {
|
|
line, err := resp.ReadString('\n')
|
|
if err != nil && err != io.EOF {
|
|
log.Fatalln("Failed to read HTML response line-by-line:", err.Error())
|
|
} else if err != nil && err == io.EOF {
|
|
break
|
|
}
|
|
|
|
if headCurrentlyParsing {
|
|
// Check for go-import data.
|
|
if strings.Contains(line, `<meta name="go-import"`) {
|
|
// Get content.
|
|
// Import things are in element #4.
|
|
lineSplitted := strings.Split(line, `"`)
|
|
|
|
// Check line length. This is not so good approach, but
|
|
// should work for 99% of dependencies.
|
|
if len(lineSplitted) < 5 {
|
|
log.Println("Got line: '" + line + "', but it cannot be parsed. Probably badly formed - tag itself appears to be incomplete. Skipping")
|
|
continue
|
|
}
|
|
|
|
if len(lineSplitted) > 5 {
|
|
log.Println("Got line: '" + line + "', but it cannot be parsed. Probably badly formed - line where meta tag is located appears to be too long. Skipping")
|
|
continue
|
|
}
|
|
|
|
// Import line contains data like VCS name and VCS URL.
|
|
// They're delimited with whitespace.
|
|
importDataSplitted := strings.Split(lineSplitted[3], " ")
|
|
|
|
// Import line should contain at least 3 elements.
|
|
if len(importDataSplitted) < 3 {
|
|
log.Println("Got line: '" + line + "', but it cannot be parsed. Probably badly formed - import data is too small. Skipping")
|
|
continue
|
|
}
|
|
|
|
// Fill dependency data with this data.
|
|
// First element is a module name and we do not actually
|
|
// need it, because it is already filled previously.
|
|
dependency.VCS.VCS = importDataSplitted[1]
|
|
dependency.VCS.VCSPath = importDataSplitted[2]
|
|
}
|
|
|
|
// Check for go-source data.
|
|
if strings.Contains(line, `<meta name="go-source"`) {
|
|
// Get content.
|
|
// Import things are in element #4.
|
|
lineSplitted := strings.Split(line, `"`)
|
|
|
|
// Check line length. This is not so good approach, but
|
|
// should work for 99% of dependencies.
|
|
if len(lineSplitted) < 5 {
|
|
log.Println("Got line: '" + line + "', but it cannot be parsed. Probably badly formed - tag itself appears to be incomplete. Skipping")
|
|
continue
|
|
}
|
|
|
|
if len(lineSplitted) > 5 {
|
|
log.Println("Got line: '" + line + "', but it cannot be parsed. Probably badly formed - line where meta tag is located appears to be too long. Skipping")
|
|
continue
|
|
}
|
|
|
|
// Source line contains data like VCS paths templates.
|
|
// They're delimited with whitespace.
|
|
sourceDataSplitted := strings.Split(lineSplitted[3], " ")
|
|
|
|
// Source data line should contain at least 3 elements.
|
|
if len(sourceDataSplitted) < 4 {
|
|
log.Println("Got line: '" + line + "', but it cannot be parsed. Probably badly formed - source data is too small. Skipping")
|
|
continue
|
|
}
|
|
|
|
// Fill dependency data.
|
|
dependency.VCS.SourceURLDirTemplate = sourceDataSplitted[2]
|
|
dependency.VCS.SourceURLFileTemplate = sourceDataSplitted[3]
|
|
}
|
|
}
|
|
|
|
if strings.Contains(strings.ToLower(line), "<head>") {
|
|
headCurrentlyParsing = true
|
|
}
|
|
|
|
if strings.Contains(strings.ToLower(line), "</head>") {
|
|
headCurrentlyParsing = false
|
|
}
|
|
}
|
|
|
|
if configuration.Cfg.Log.Debug {
|
|
log.Printf("go-import and go-source data parsed: %+v\n", dependency.VCS)
|
|
}
|
|
}
|