Example #1
0
func LoadConfig() (Config, error) {
	// Try the cache first.
	if configCache != nil {
		return configCache, nil
	}

	// Load the local config.
	var local LocalConfig
	if err := config.UnmarshalLocalConfig(&local); err != nil {
		return nil, err
	}

	labels := &local.PT.Labels
	if labels.PointMeLabel == "" {
		labels.PointMeLabel = DefaultPointMeLabel
	}
	if labels.ImplementedLabel == "" {
		labels.ImplementedLabel = DefaultImplementedLabel
	}
	if labels.NoReviewLabel == "" {
		labels.NoReviewLabel = DefaultNoReviewLabel
	}
	if labels.ReviewedLabel == "" {
		labels.ReviewedLabel = DefaultReviewedLabel
	}
	labels.SkipCheckLabels = append(labels.SkipCheckLabels, DefaultSkipCheckLabels...)

	if err := local.validate(); err != nil {
		return nil, err
	}

	// Load the global config.
	var global GlobalConfig
	if err := config.UnmarshalGlobalConfig(&global); err != nil {
		return nil, err
	}
	if err := global.validate(); err != nil {
		return nil, err
	}

	// Load git config.
	storyFilter, err := git.GetConfigString("salsaflow.pivotaltracker.include-stories")
	if err != nil {
		return nil, err
	}

	var storyFilterRe *regexp.Regexp
	if storyFilter != "" {
		var err error
		storyFilterRe, err = regexp.Compile(storyFilter)
		if err != nil {
			return nil, err
		}
	}

	configCache = &configProxy{&local, &global, storyFilterRe}
	return configCache, nil
}
Example #2
0
// ParseUpstreamURL parses the URL of the git upstream being used by SalsaFlow
// and returns the given GitHub owner and repository.
func ParseUpstreamURL() (owner, repo string, err error) {
	// Load the Git config.
	gitConfig, err := git.LoadConfig()
	if err != nil {
		return "", "", err
	}
	remoteName := gitConfig.RemoteName

	// Get the upstream URL.
	task := fmt.Sprintf("Get URL for git remote '%v'", remoteName)
	remoteURL, err := git.GetConfigString(fmt.Sprintf("remote.%v.url", remoteName))
	if err != nil {
		return "", "", errs.NewError(task, err)
	}

	// Parse it and return the result.
	return parseUpstreamURL(remoteURL)
}
Example #3
0
func Init(force bool) error {
	// Check whether the repository has been initialised yet.
	task := "Check whether the repository has been initialised"
	versionString, err := git.GetConfigString("salsaflow.initialised")
	if err != nil {
		return errs.NewError(task, err)
	}
	if versionString == metadata.Version && !force {
		return errs.NewError(task, ErrInitialised)
	}

	log.Log("Initialising the repository for SalsaFlow")

	// Make sure the user is using the right version of Git.
	//
	// The check is here and not in app.Init because it is highly improbable
	// that the check would pass once and then fail later. Once the right
	// version of git is installed, it most probably stays.
	task = "Check the git version being used"
	log.Run(task)
	stdout, err := git.Run("--version")
	if err != nil {
		return errs.NewError(task, err)
	}
	pattern := regexp.MustCompile("^git version (([0-9]+)[.]([0-9]+).*)")
	parts := pattern.FindStringSubmatch(stdout.String())
	if len(parts) != 4 {
		return errs.NewError(task, errors.New("unexpected git --version output"))
	}
	gitVersion := parts[1]
	// This cannot fail since we matched the regexp.
	major, _ := strconv.Atoi(parts[2])
	minor, _ := strconv.Atoi(parts[3])
	// We need Git version 1.8.5.4+, so let's require 1.9+.
	switch {
	case major >= 2:
		// OK
	case major == 1 && minor >= 9:
		// OK
	default:
		hint := `
You need Git version 1.9.0 or newer.

`
		return errs.NewErrorWithHint(
			task,
			errors.New("unsupported git version detected: "+gitVersion),
			hint)
	}

	// Get hold of a git config instance.
	gitConfig, err := git.LoadConfig()
	if err != nil {
		return err
	}
	var (
		remoteName   = gitConfig.RemoteName
		trunkBranch  = gitConfig.TrunkBranchName
		stableBranch = gitConfig.StableBranchName
	)

	// Make sure that the stable branch exists.
	task = fmt.Sprintf("Make sure branch '%v' exists", stableBranch)
	log.Run(task)
	err = git.CheckOrCreateTrackingBranch(stableBranch, remoteName)
	if err != nil {
		if ex, ok := err.(*git.ErrRefNotFound); ok {
			hint := fmt.Sprintf(
				"Make sure that branch '%v' exists and run init again.\n", ex.Ref)
			return errs.NewErrorWithHint(task, err, hint)
		} else if _, ok := err.(*git.ErrRefNotInSync); !ok {
			// We ignore ErrRefNotInSync here, so return the error
			// in case it is of some other kind.
			return errs.NewError(task, err)
		}
	}

	// Make sure that the trunk branch exists.
	task = fmt.Sprintf("Make sure branch '%v' exists", trunkBranch)
	log.Run(task)
	err = git.CheckOrCreateTrackingBranch(trunkBranch, remoteName)
	if err != nil {
		if _, ok := err.(*git.ErrRefNotFound); ok {
			task := fmt.Sprintf("Create branch '%v'", trunkBranch)
			log.Log(fmt.Sprintf(
				"Branch '%v' not found. Will create one for you for free!", trunkBranch))
			if err := git.Branch(trunkBranch, stableBranch); err != nil {
				return errs.NewError(task, err)
			}
			log.NewLine(fmt.Sprintf(
				"The newly created branch is pointing to '%v'.", stableBranch))

			task = fmt.Sprintf("Push branch '%v' to remote '%v'", trunkBranch, remoteName)
			log.Run(task)
			if err := git.Push(remoteName, trunkBranch+":"+trunkBranch); err != nil {
				return errs.NewError(task, err)
			}
		} else if _, ok := err.(*git.ErrRefNotInSync); !ok {
			// We ignore ErrRefNotInSync here, so return the error
			// in case it is of some other kind.
			return errs.NewError(task, err)
		}
	}

	// Verify our git hooks are installed and used.
	for _, kind := range hooks.HookTypes {
		task := fmt.Sprintf("Check the current git %v hook", kind)
		log.Run(task)
		if err := hooks.CheckAndUpsert(kind, force); err != nil {
			return errs.NewError(task, err)
		}
	}

	// Run other registered init hooks.
	task = "Running the registered repository init hooks"
	log.Log(task)
	if err := executeInitHooks(); err != nil {
		return errs.NewError(task, err)
	}

	// Success! Mark the repository as initialised in git config.
	task = "Mark the repository as initialised"
	if err := git.SetConfigString("salsaflow.initialised", metadata.Version); err != nil {
		return err
	}
	asciiart.PrintThumbsUp()
	fmt.Println()
	log.Log("The repository is initialised")

	return nil
}