<commit_before>package ps

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"github.com/dokku/dokku/plugins/common"
	dockeroptions "github.com/dokku/dokku/plugins/docker-options"
	"github.com/ryanuber/columnize"
)

func canScaleApp(appName string) bool {
	return !common.FileExists(getScalefileExtractedPath(appName))
}

func extractProcfile(appName, image string, procfilePath string) error {
	if err := removeProcfile(appName); err != nil {
		return err
	}

	destination := getProcfilePath(appName)
	common.CopyFromImage(appName, image, "Procfile", destination)
	if !common.FileExists(destination) {
		common.LogInfo1Quiet("No Procfile found in app image")
		return nil
	}

	common.LogInfo1Quiet("App Procfile file found")
	checkCmd := common.NewShellCmd(strings.Join([]string{
		"procfile-util",
		"check",
		"--procfile",
		destination,
	}, " "))
	var stderr bytes.Buffer
	checkCmd.ShowOutput = false
	checkCmd.Command.Stderr = &stderr
	_, err := checkCmd.Output()

	if err != nil {
		return fmt.Errorf(strings.TrimSpace(stderr.String()))
	}

	return nil
}

func extractOrGenerateScalefile(appName string, image string) error {
	destination := getScalefilePath(appName)
	extracted := getScalefileExtractedPath(appName)
	previouslyExtracted := common.FileExists(extracted)

	if err := common.CopyFromImage(appName, image, "DOKKU_SCALE", extracted); err != nil {
		if previouslyExtracted {
			os.Remove(destination)
		}
		os.Remove(extracted)
	} else if err := common.CopyFile(extracted, destination); err != nil {
		return err
	}

	if common.FileExists(destination) {
		common.LogInfo1Quiet("DOKKU_SCALE file exists")
		return nil
	}

	common.LogInfo1Quiet("DOKKU_SCALE file not found in app image. Generating one based on Procfile...")
	if err := updateScalefile(appName, make(map[string]int)); err != nil {
		common.LogDebug(fmt.Sprintf("Error generating scale file: %s", err.Error()))
		return err
	}
	return nil
}

func generateScalefile(appName string) error {
	destination := getScalefilePath(appName)
	procfilePath := getProcfilePath(appName)
	content := []string{"web=1"}
	if !common.FileExists(procfilePath) {
		return common.WriteSliceToFile(destination, content)
	}
<commit_msg>fix: ensure the scale file has correct processes when it exists<commit_after>package ps

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"github.com/dokku/dokku/plugins/common"
	dockeroptions "github.com/dokku/dokku/plugins/docker-options"
	"github.com/ryanuber/columnize"
)

func canScaleApp(appName string) bool {
	return !common.FileExists(getScalefileExtractedPath(appName))
}

func extractProcfile(appName, image string, procfilePath string) error {
	if err := removeProcfile(appName); err != nil {
		return err
	}

	destination := getProcfilePath(appName)
	common.CopyFromImage(appName, image, "Procfile", destination)
	if !common.FileExists(destination) {
		common.LogInfo1Quiet("No Procfile found in app image")
		return nil
	}

	common.LogInfo1Quiet("App Procfile file found")
	checkCmd := common.NewShellCmd(strings.Join([]string{
		"procfile-util",
		"check",
		"--procfile",
		destination,
	}, " "))
	var stderr bytes.Buffer
	checkCmd.ShowOutput = false
	checkCmd.Command.Stderr = &stderr
	_, err := checkCmd.Output()

	if err != nil {
		return fmt.Errorf(strings.TrimSpace(stderr.String()))
	}

	return nil
}

func extractOrGenerateScalefile(appName string, image string) error {
	destination := getScalefilePath(appName)
	extracted := getScalefileExtractedPath(appName)
	previouslyExtracted := common.FileExists(extracted)

	if err := common.CopyFromImage(appName, image, "DOKKU_SCALE", extracted); err != nil {
		if previouslyExtracted {
			os.Remove(destination)
		}
		os.Remove(extracted)
	} else if err := common.CopyFile(extracted, destination); err != nil {
		return err
	}

	if common.FileExists(destination) {
		common.LogInfo1Quiet("DOKKU_SCALE file exists")
		return updateScalefile(appName, make(map[string]int))
	}

	common.LogInfo1Quiet("DOKKU_SCALE file not found in app image. Generating one based on Procfile...")
	if err := updateScalefile(appName, make(map[string]int)); err != nil {
		common.LogDebug(fmt.Sprintf("Error generating scale file: %s", err.Error()))
		return err
	}
	return nil
}

func generateScalefile(appName string) error {
	destination := getScalefilePath(appName)
	procfilePath := getProcfilePath(appName)
	content := []string{"web=1"}
	if !common.FileExists(procfilePath) {
		return common.WriteSliceToFile(destination, content)
	}

{'fraction_non_alphanumeric': 0.12371134020618557, 'fraction_numerical': 0.0021934634788330775, 'mean_word_length': 5.298342541436464, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '886272', 'n_tokens_mistral': 1615, 'n_tokens_neox': 1544, 'n_words': 331}