示例#1
0
文件: vcs.go 项目: albrow/glide
// VcsGet figures out how to fetch a dependency, and then gets it.
//
// VcsGet installs into the cache.
func VcsGet(dep *cfg.Dependency) error {

	key, err := cp.Key(dep.Remote())
	if err != nil {
		msg.Die("Cache key generation error: %s", err)
	}
	location := cp.Location()
	d := filepath.Join(location, "src", key)

	repo, err := dep.GetRepo(d)
	if err != nil {
		return err
	}
	// If the directory does not exist this is a first cache.
	if _, err = os.Stat(d); os.IsNotExist(err) {
		msg.Debug("Adding %s to the cache for the first time", dep.Name)
		err = repo.Get()
		if err != nil {
			return err
		}
		branch := findCurrentBranch(repo)
		if branch != "" {
			msg.Debug("Saving default branch for %s", repo.Remote())
			c := cp.RepoInfo{DefaultBranch: branch}
			err = cp.SaveRepoData(key, c)
			if err == cp.ErrCacheDisabled {
				msg.Debug("Unable to cache default branch because caching is disabled")
			} else if err != nil {
				msg.Debug("Error saving %s to cache. Error: %s", repo.Remote(), err)
			}
		}
	} else {
		msg.Debug("Updating %s in the cache", dep.Name)
		err = repo.Update()
		if err != nil {
			return err
		}
	}

	return nil
}
示例#2
0
func wizardFindVersions(d *cfg.Dependency) {
	l, err := cache.Location()
	if err != nil {
		msg.Debug("Problem detecting cache location: %s", err)
		return
	}
	var remote string
	if d.Repository != "" {
		remote = d.Repository
	} else {
		remote = "https://" + d.Name
	}

	key, err := cache.Key(remote)
	if err != nil {
		msg.Debug("Problem generating cache key for %s: %s", remote, err)
		return
	}

	local := filepath.Join(l, "src", key)
	repo, err := vcs.NewRepo(remote, local)
	if err != nil {
		msg.Debug("Problem getting repo instance: %s", err)
		return
	}

	var useLocal bool
	if _, err = os.Stat(local); err == nil {
		useLocal = true
	}

	// Git endpoints allow for querying without fetching the codebase locally.
	// We try that first to avoid fetching right away. Is this premature
	// optimization?
	cc := true
	if !useLocal && repo.Vcs() == vcs.Git {
		out, err2 := exec.Command("git", "ls-remote", remote).CombinedOutput()
		if err2 == nil {
			cache.MemTouch(remote)
			cc = false
			lines := strings.Split(string(out), "\n")
			for _, i := range lines {
				ti := strings.TrimSpace(i)
				if found := createGitParseVersion.FindString(ti); found != "" {
					tg := strings.TrimPrefix(strings.TrimSuffix(found, "^{}"), "tags/")
					cache.MemPut(remote, tg)
					if d.Reference != "" && strings.HasPrefix(ti, d.Reference) {
						cache.MemSetCurrent(remote, tg)
					}
				}
			}
		}
	}

	if cc {
		cache.Lock(key)
		cache.MemTouch(remote)
		if _, err = os.Stat(local); os.IsNotExist(err) {
			repo.Get()
			branch := findCurrentBranch(repo)
			c := cache.RepoInfo{DefaultBranch: branch}
			err = cache.SaveRepoData(key, c)
			if err != nil {
				msg.Debug("Error saving cache repo details: %s", err)
			}
		} else {
			repo.Update()
		}
		tgs, err := repo.Tags()
		if err != nil {
			msg.Debug("Problem getting tags: %s", err)
		} else {
			for _, v := range tgs {
				cache.MemPut(remote, v)
			}
		}
		if d.Reference != "" && repo.IsReference(d.Reference) {
			tgs, err = repo.TagsFromCommit(d.Reference)
			if err != nil {
				msg.Debug("Problem getting tags for commit: %s", err)
			} else {
				if len(tgs) > 0 {
					for _, v := range tgs {
						if !(repo.Vcs() == vcs.Hg && v == "tip") {
							cache.MemSetCurrent(remote, v)
						}
					}
				}
			}
		}
		cache.Unlock(key)
	}
}
示例#3
0
文件: vcs.go 项目: heewa/glide
// defaultBranch tries to ascertain the default branch for the given repo.
// Some repos will have multiple branches in them (e.g. Git) while others
// (e.g. Svn) will not.
func defaultBranch(repo v.Repo, home string) string {

	// Svn and Bzr use different locations (paths or entire locations)
	// for branches so we won't have a default branch.
	if repo.Vcs() == v.Svn || repo.Vcs() == v.Bzr {
		return ""
	}

	// Check the cache for a value.
	key, kerr := cp.Key(repo.Remote())
	var d cp.RepoInfo
	if kerr == nil {
		d, err := cp.RepoData(key)
		if err == nil {
			if d.DefaultBranch != "" {
				return d.DefaultBranch
			}
		}
	}

	// If we don't have it in the store try some APIs
	r := repo.Remote()
	u, err := url.Parse(r)
	if err != nil {
		return ""
	}
	if u.Scheme == "" {
		// Where there is no scheme we try urls like [email protected]:foo/bar
		r = strings.Replace(r, ":", "/", -1)
		r = "ssh://" + r
		u, err = url.Parse(r)
		if err != nil {
			return ""
		}
		u.Scheme = ""
	}
	if u.Host == "github.com" {
		parts := strings.Split(u.Path, "/")
		if len(parts) != 2 {
			return ""
		}
		api := fmt.Sprintf("https://api.github.com/repos/%s/%s", parts[0], parts[1])
		resp, err := http.Get(api)
		if err != nil {
			return ""
		}
		defer resp.Body.Close()
		if resp.StatusCode >= 300 || resp.StatusCode < 200 {
			return ""
		}
		body, err := ioutil.ReadAll(resp.Body)
		var data interface{}
		err = json.Unmarshal(body, &data)
		if err != nil {
			return ""
		}
		gh := data.(map[string]interface{})
		db := gh["default_branch"].(string)
		if kerr == nil {
			d.DefaultBranch = db
			err := cp.SaveRepoData(key, d)
			if err == cp.ErrCacheDisabled {
				msg.Debug("Unable to cache default branch because caching is disabled")
			} else if err != nil {
				msg.Debug("Error saving %s to cache. Error: %s", repo.Remote(), err)
			}
		}
		return db
	}

	if u.Host == "bitbucket.org" {
		parts := strings.Split(u.Path, "/")
		if len(parts) != 2 {
			return ""
		}
		api := fmt.Sprintf("https://bitbucket.org/api/1.0/repositories/%s/%s/main-branch/", parts[0], parts[1])
		resp, err := http.Get(api)
		if err != nil {
			return ""
		}
		defer resp.Body.Close()
		if resp.StatusCode >= 300 || resp.StatusCode < 200 {
			return ""
		}
		body, err := ioutil.ReadAll(resp.Body)
		var data interface{}
		err = json.Unmarshal(body, &data)
		if err != nil {
			return ""
		}
		bb := data.(map[string]interface{})
		db := bb["name"].(string)
		if kerr == nil {
			d.DefaultBranch = db
			err := cp.SaveRepoData(key, d)
			if err == cp.ErrCacheDisabled {
				msg.Debug("Unable to cache default branch because caching is disabled")
			} else if err != nil {
				msg.Debug("Error saving %s to cache. Error: %s", repo.Remote(), err)
			}
		}
		return db
	}

	return ""
}
示例#4
0
文件: vcs.go 项目: heewa/glide
// VcsGet figures out how to fetch a dependency, and then gets it.
//
// VcsGet installs into the dest.
func VcsGet(dep *cfg.Dependency, dest, home string, cache, cacheGopath, useGopath bool) error {
	// When not skipping the $GOPATH look in it for a copy of the package
	if useGopath {
		// Check if the $GOPATH has a viable version to use and if so copy to vendor
		gps := gpath.Gopaths()
		for _, p := range gps {
			d := filepath.Join(p, "src", dep.Name)
			if _, err := os.Stat(d); err == nil {
				empty, err := gpath.IsDirectoryEmpty(d)
				if empty || err != nil {
					continue
				}

				repo, err := dep.GetRepo(d)
				if err != nil {
					continue
				}

				// Dirty repos have uncommitted changes.
				if repo.IsDirty() {
					continue
				}

				// Having found a repo we copy it to vendor and update it.
				msg.Info("Copying package %s from the GOPATH.", dep.Name)
				msg.Debug("Found %s in GOPATH at %s. Copying to %s", dep.Name, d, dest)
				err = gpath.CopyDir(d, dest)
				if err != nil {
					return err
				}

				// Update the repo in the vendor directory
				msg.Debug("Updating %s, now in the vendor path at %s", dep.Name, dest)
				repo, err = dep.GetRepo(dest)
				if err != nil {
					return err
				}
				err = repo.Update()
				if err != nil {
					return err
				}

				// If there is no reference set on the dep we try to checkout
				// the default branch.
				if dep.Reference == "" {
					db := defaultBranch(repo, home)
					if db != "" {
						err = repo.UpdateVersion(db)
						if err != nil && msg.Default.IsDebugging {
							msg.Debug("Attempting to set the version on %s to %s failed. Error %s", dep.Name, db, err)
						}
					}
				}
				return nil
			}
		}
	}

	// When opting in to cache in the GOPATH attempt to do put a copy there.
	if cacheGopath {

		// Since we didn't find an existing copy in the GOPATHs try to clone there.
		gp := gpath.Gopath()
		if gp != "" {
			d := filepath.Join(gp, "src", dep.Name)
			if _, err := os.Stat(d); os.IsNotExist(err) {
				// Empty directory so we checkout out the code here.
				msg.Debug("Retrieving %s to %s before copying to vendor", dep.Name, d)
				repo, err := dep.GetRepo(d)
				if err != nil {
					return err
				}
				repo.Get()

				branch := findCurrentBranch(repo)
				if branch != "" {
					// we know the default branch so we can store it in the cache
					var loc string
					if dep.Repository != "" {
						loc = dep.Repository
					} else {
						loc = "https://" + dep.Name
					}
					key, err := cp.Key(loc)
					if err == nil {
						msg.Debug("Saving default branch for %s", repo.Remote())
						c := cp.RepoInfo{DefaultBranch: branch}
						err = cp.SaveRepoData(key, c)
						if msg.Default.IsDebugging && err == cp.ErrCacheDisabled {
							msg.Debug("Unable to cache default branch because caching is disabled")
						}
					}
				}

				msg.Debug("Copying %s from GOPATH at %s to %s", dep.Name, d, dest)
				err = gpath.CopyDir(d, dest)
				if err != nil {
					return err
				}

				return nil
			}
		}
	}

	// If opting in to caching attempt to put it in the cache folder
	if cache {
		// Check if the cache has a viable version and try to use that.
		var loc string
		if dep.Repository != "" {
			loc = dep.Repository
		} else {
			loc = "https://" + dep.Name
		}
		key, err := cp.Key(loc)
		if err == nil {
			location, err := cp.Location()
			if err != nil {
				return err
			}
			d := filepath.Join(location, "src", key)

			repo, err := dep.GetRepo(d)
			if err != nil {
				return err
			}
			// If the directory does not exist this is a first cache.
			if _, err = os.Stat(d); os.IsNotExist(err) {
				msg.Debug("Adding %s to the cache for the first time", dep.Name)
				err = repo.Get()
				if err != nil {
					return err
				}
				branch := findCurrentBranch(repo)
				if branch != "" {
					// we know the default branch so we can store it in the cache
					var loc string
					if dep.Repository != "" {
						loc = dep.Repository
					} else {
						loc = "https://" + dep.Name
					}
					key, err := cp.Key(loc)
					if err == nil {
						msg.Debug("Saving default branch for %s", repo.Remote())
						c := cp.RepoInfo{DefaultBranch: branch}
						err = cp.SaveRepoData(key, c)
						if err == cp.ErrCacheDisabled {
							msg.Debug("Unable to cache default branch because caching is disabled")
						} else if err != nil {
							msg.Debug("Error saving %s to cache. Error: %s", repo.Remote(), err)
						}
					}
				}

			} else {
				msg.Debug("Updating %s in the cache", dep.Name)
				err = repo.Update()
				if err != nil {
					return err
				}
			}

			msg.Debug("Copying %s from the cache to %s", dep.Name, dest)
			err = gpath.CopyDir(d, dest)
			if err != nil {
				return err
			}

			return nil
		}

		msg.Warn("Cache key generation error: %s", err)
	}

	// If unable to cache pull directly into the vendor/ directory.
	repo, err := dep.GetRepo(dest)
	if err != nil {
		return err
	}

	gerr := repo.Get()

	// Attempt to cache the default branch
	if cache {
		if branch := findCurrentBranch(repo); branch != "" {
			// we know the default branch so we can store it in the cache
			var loc string
			if dep.Repository != "" {
				loc = dep.Repository
			} else {
				loc = "https://" + dep.Name
			}
			key, err := cp.Key(loc)
			if err == nil {
				msg.Debug("Saving default branch for %s", repo.Remote())
				c := cp.RepoInfo{DefaultBranch: branch}
				err = cp.SaveRepoData(key, c)
				if err == cp.ErrCacheDisabled {
					msg.Debug("Unable to cache default branch because caching is disabled")
				} else if err != nil {
					msg.Debug("Error saving %s to cache - Error: %s", repo.Remote(), err)
				}
			}
		}
	}

	return gerr
}