Skip to content

Commit

Permalink
version v0.0.4, changed from commits to versions
Browse files Browse the repository at this point in the history
  • Loading branch information
costaluu committed Sep 26, 2024
1 parent 37904f5 commit 523373a
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 212 deletions.
18 changes: 9 additions & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [Key Features](#key-features)
- [Blocks](#blocks)
- [Delimiters](#delimiters)
- [Commits](#commits)
- [Versions](#versions)
- [Commands](#commands)
- [Getting Started](#getting-started)

Expand All @@ -21,15 +21,15 @@

Feature flagging has become a critical tool for controlled feature deployment, but **Flag** takes this to the next level by allowing feature toggling at the **file level**. Instead of toggling functionality purely in code, Flag modifies actual file content based on active features.

By leveraging Git, Flag ensures that changes are versioned, tracked, and consistent across your codebase. Features can be managed dynamically through **blocks**, **delimiters**, and **commits**, with seamless Git integration to track every change.
By leveraging Git, Flag ensures that changes are versioned, tracked, and consistent across your codebase. Features can be managed dynamically through **blocks**, **delimiters**, and **versions**, with seamless Git integration to track every change.

---

## Key Features

- **File-based Feature Toggling**: Modify file content dynamically based on active features.
- **Git Integration**: Works only within Git repositories for version control and tracking.
- **Blocks, Delimiters, and Commits**: Three core concepts for managing features in code and configuration files.
- **Blocks, Delimiters, and Versions**: Three core concepts for managing features in code and configuration files.
- **Branch-based**: Feature flags are isolated at the branch level, allowing for granular control.

---
Expand Down Expand Up @@ -72,13 +72,13 @@ These operations let you fully control how Flag identifies and processes blocks

---

## Commits
## Versions

In cases where block delimiters are not allowed (such as JSON files, which do not support comments), Flag uses Commits to manage features.
In cases where block delimiters are not allowed (such as JSON files, which do not support comments), Flag uses Versions to manage features.

### Commit Workflow:
### Version Workflow:

1. Create a base commit: `flag commits base`
1. Create a base version: `flag versions base`
This creates a base reference of the files to start tracking features.
2. Sync features

Expand Down Expand Up @@ -110,7 +110,7 @@ COMMANDS:
report shows a workspace report of features
delimeters operations for delimiters
blocks operations for block features
commits operations for commit-based features
versions operations for version-based features
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
Expand All @@ -126,4 +126,4 @@ GLOBAL OPTIONS:
2. Initialize Workspace: Run flag init to create a new workspace in your Git repository.
3. Define Feature Blocks: Use the @feature and @default block structure in your files.
4. Manage Delimiters: Set up delimiters using flag delimeters set.
5. Handle Files Without Comments: Use commits-based tracking with flag commits base and flag sync.
5. Handle Files Without Comments: Use versions-based tracking with flag versions base and flag sync.
8 changes: 4 additions & 4 deletions src/commands/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ var ReportCommand *cli.Command = &cli.Command{
Name: "report",
Usage: "shows a workspace report of features",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "commits", Aliases: []string{"c"}},
&cli.BoolFlag{Name: "versions", Aliases: []string{"c"}},
&cli.BoolFlag{Name: "blocks", Aliases: []string{"b"}},
},
Action: func(ctx *cli.Context) error {
if ctx.Bool("commits") && ctx.Bool("blocks") {
if ctx.Bool("versions") && ctx.Bool("blocks") {
core.WorkspaceReport()
} else if ctx.Bool("commits") {
core.AllCommitDetails()
} else if ctx.Bool("versions") {
core.AllVersionFeatureDetails()
} else if ctx.Bool("blocks") {
core.AllBlocksDetails()
} else {
Expand Down
70 changes: 35 additions & 35 deletions src/commands/commits.go → src/commands/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import (
"github.com/urfave/cli/v2"
)

var CommitsFeaturesToggleCommand *cli.Command = &cli.Command{
var VersionsFeaturesToggleCommand *cli.Command = &cli.Command{
Name: "toggle",
Usage: "toggle a feature to on or off",
ArgsUsage: `<feature_name> <on|off>`,
Action: func(ctx *cli.Context) error {
args := ctx.Args().Slice()

if len(args) < 2 {
logger.Result[string](fmt.Sprintf("usage: %s commits %s %s", constants.COMMAND, ctx.Command.Name, ctx.Command.ArgsUsage))
logger.Result[string](fmt.Sprintf("usage: %s versions %s %s", constants.COMMAND, ctx.Command.Name, ctx.Command.ArgsUsage))
}

state := strings.ToUpper(args[1])
Expand All @@ -28,51 +28,51 @@ var CommitsFeaturesToggleCommand *cli.Command = &cli.Command{
logger.Result[string]("invalid state. use on|off")
}

core.ToggleCommitFeature(args[0], state)
core.ToggleVersionFeature(args[0], state)

return nil
},
}

var CommitsFeaturesPromoteCommand *cli.Command = &cli.Command{
var VersionsFeaturesPromoteCommand *cli.Command = &cli.Command{
Name: "promote",
Usage: "promote a feature or state",
Action: func(ctx *cli.Context) error {
core.CommitPromote(true)
core.VersionPromote(true)

return nil
},
}

var CommitsFeaturesDemoteCommand *cli.Command = &cli.Command{
var VersionsFeaturesDemoteCommand *cli.Command = &cli.Command{
Name: "demote",
Usage: "demote a feature",
ArgsUsage: `<feature_name>`,
Action: func(ctx *cli.Context) error {
core.CommitDemote(true)
core.VersionDemote(true)

return nil
},
}

var CommitsFeaturesBaseCommand *cli.Command = &cli.Command{
var VersionsFeaturesBaseCommand *cli.Command = &cli.Command{
Name: "base",
Usage: "create a base commit feature",
Usage: "create a base for a feature",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "skip-form", Aliases: []string{"sf"}},
},
Action: func(ctx *cli.Context) error {
selectedItem := utils.PickAllFiles("Pick a file to make a commit base")
selectedItem := utils.PickAllFiles("Pick a file to make a base verrsion")

if selectedItem.ItemTitle != "" {
core.CommitBase(selectedItem.ItemTitle, ctx.Bool("skip-form"))
core.VersionBase(selectedItem.ItemTitle, ctx.Bool("skip-form"))
}

return nil
},
}

var CommitsFeaturesNewFeatureCommand *cli.Command = &cli.Command{
var VersionsFeaturesNewFeatureCommand *cli.Command = &cli.Command{
Name: "new-feature",
Usage: "create a new feature with the current changes of a file",
ArgsUsage: `<feature_name>`,
Expand All @@ -83,76 +83,76 @@ var CommitsFeaturesNewFeatureCommand *cli.Command = &cli.Command{
args := ctx.Args().Slice()

if len(args) < 1 {
logger.Result[string](fmt.Sprintf("usage: %s commits %s %s", constants.COMMAND, ctx.Command.Name, ctx.Command.ArgsUsage))
logger.Result[string](fmt.Sprintf("usage: %s versions %s %s", constants.COMMAND, ctx.Command.Name, ctx.Command.ArgsUsage))
}

if len(args[0]) < constants.MIN_FEATURE_CHARACTERS {
logger.Result[string](fmt.Sprintf("a feature name should have at least %d characters", constants.MIN_FEATURE_CHARACTERS))
}

selectedItem := utils.PickModifedOrUntrackedFiles("Select the commit base that the new feature will be created")
selectedItem := utils.PickModifedOrUntrackedFiles("Select the base version that the new feature will be created")

if selectedItem.ItemTitle != "" {
core.CommitNewFeature(selectedItem.ItemTitle, args[0], ctx.Bool("skip-form"), true)
core.VersionNewFeature(selectedItem.ItemTitle, args[0], ctx.Bool("skip-form"), true)
}

return nil
},
}

var CommitsFeaturesSaveCommand *cli.Command = &cli.Command{
var VersionsFeaturesSaveCommand *cli.Command = &cli.Command{
Name: "save",
Usage: "save current changes of a file to a feature or state",
Action: func(ctx *cli.Context) error {
selectedItem := utils.PickModifedOrUntrackedFiles("Select the commit base that the changes will be saved")
selectedItem := utils.PickModifedOrUntrackedFiles("Select the base version that the changes will be saved")

if selectedItem.ItemTitle != "" {
core.CommitSave(selectedItem.ItemTitle, true)
core.VersionSave(selectedItem.ItemTitle, true)
}

return nil
},
}

var CommitsFeaturesDeleteCommand *cli.Command = &cli.Command{
var VersionsFeaturesDeleteCommand *cli.Command = &cli.Command{
Name: "delete",
Usage: "delete a feature or state",
Action: func(ctx *cli.Context) error {
selectedItem := utils.PickModifedOrUntrackedFiles("Select the commit base to delete")
selectedItem := utils.PickModifedOrUntrackedFiles("Select the base version base to delete")

if selectedItem.ItemTitle != "" {
core.CommitDelete(selectedItem.ItemTitle, true)
core.VersionDelete(selectedItem.ItemTitle, true)
}

return nil
},
}

var CommitsFeaturesDetailsCommand *cli.Command = &cli.Command{
var VersionsFeaturesDetailsCommand *cli.Command = &cli.Command{
Name: "details",
Usage: "show a report for a commit base",
Usage: "shows a feature report of a base version",
Action: func(ctx *cli.Context) error {
selectedItem := utils.PickAllFiles("Pick a file to show details")

if selectedItem.ItemTitle != "" {
core.CommitDetailsFromPath(selectedItem.ItemTitle)
core.VersionFeatureDetailsFromPath(selectedItem.ItemTitle)
}

return nil
},
}

var CommitsFeaturesCommand *cli.Command = &cli.Command{
Name: "commits",
Usage: "operations for commits features",
var VersionsFeaturesCommand *cli.Command = &cli.Command{
Name: "versions",
Usage: "operations for versions features",
Subcommands: []*cli.Command{
CommitsFeaturesToggleCommand,
CommitsFeaturesPromoteCommand,
CommitsFeaturesDemoteCommand,
CommitsFeaturesBaseCommand,
CommitsFeaturesNewFeatureCommand,
CommitsFeaturesSaveCommand,
CommitsFeaturesDeleteCommand,
CommitsFeaturesDetailsCommand,
VersionsFeaturesToggleCommand,
VersionsFeaturesPromoteCommand,
VersionsFeaturesDemoteCommand,
VersionsFeaturesBaseCommand,
VersionsFeaturesNewFeatureCommand,
VersionsFeaturesSaveCommand,
VersionsFeaturesDeleteCommand,
VersionsFeaturesDetailsCommand,
},
}
2 changes: 1 addition & 1 deletion src/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "github.com/charmbracelet/lipgloss"
var (
APP_NAME = "flag"
COMMAND = "flag"
VERSION = "v0.0.3"
VERSION = "v0.0.4"
MIN_FEATURE_CHARACTERS = 5
ID_LENGTH = 25
)
Expand Down
38 changes: 21 additions & 17 deletions src/core/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,34 @@ func handleDeleted(path string) {
filesystem.FileDeleteFolder(filepath.Join(rootDir, "blocks", hashedPath))
}

commitExists := filesystem.FileFolderExists(filepath.Join(rootDir, "commits", hashedPath))
versionExists := filesystem.FileFolderExists(filepath.Join(rootDir, "versions", hashedPath))

if commitExists {
filesystem.FileDeleteFolder(filepath.Join(rootDir, "commits", hashedPath))
if versionExists {
filesystem.FileDeleteFolder(filepath.Join(rootDir, "versions", hashedPath))
}
}

func handleCommit(path string) {
func handleVersion(path string) {
var rootDir string = git.GetRepositoryRoot()

hashedPath := utils.HashFilePath(path)

commitExists := filesystem.FileFolderExists(filepath.Join(rootDir, ".features", "commits", hashedPath))
versionExists := filesystem.FileFolderExists(filepath.Join(rootDir, ".features", "versions", hashedPath))

if commitExists {
if versionExists {
hasChangesWithoutSave := LookForChangesInBase(path)
name := GetCurrentStateName(path)
tree := workingtree.LoadWorkingTree(filepath.Join(rootDir, ".features", "commits", hashedPath))
features := GetCommitFeaturesFromPath(hashedPath)
tree := workingtree.LoadWorkingTree(filepath.Join(rootDir, ".features", "versions", hashedPath))
features := GetVersionFeaturesFromPath(hashedPath)

if hasChangesWithoutSave {
var options []huh.Option[string] = []huh.Option[string]{
huh.Option[string]{
Key: "Commit changes to the current feature/state" + fmt.Sprintf(" (%s)", name),
Key: "Save changes to the current feature/state" + fmt.Sprintf(" (%s)", name),
Value: "save to current state",
},
huh.Option[string]{
Key: "Commit changes to a specific feature/state",
Key: "Save changes to a specific feature/state",
Value: "save to feature/state",
},
huh.Option[string]{
Expand Down Expand Up @@ -90,12 +90,12 @@ func handleCommit(path string) {
options = newOptions
}

logger.Info[string](fmt.Sprintf("We detected untracked changes on %s that is a base commit\n", path))
logger.Info[string](fmt.Sprintf("We detected untracked changes on %s that is a version base\n", path))

selected := components.FormSelect("What should we do?", options)

if selected == "update base" {
CommitUpdateBase(path, false)
VersionUpdateBase(path, false)
} else if selected == "rebase" {
RebaseFile(path, false)
} else if selected == "create feature" {
Expand All @@ -115,11 +115,11 @@ func handleCommit(path string) {
return nil
})

CommitNewFeature(path, featureName, false, false)
VersionNewFeature(path, featureName, false, false)
} else if selected == "save to current state" {
CommitSaveToCurrentState(path)
VersionSaveToCurrentState(path)
} else if selected == "save to feature/state" {
CommitSave(path, false)
VersionSave(path, false)
} else {
BuildBaseForFile(path)
}
Expand Down Expand Up @@ -197,6 +197,10 @@ func Sync() {
if !workspaceExists {
logger.Result[string]("Workspace not found, use flag init")
}

fmt.Println(workspaceExists)

logger.Debug()

var files map[string]types.FilePathCategory = make(map[string]types.FilePathCategory)

Expand Down Expand Up @@ -241,10 +245,10 @@ func Sync() {
handleDeleted(path.Path)
} else if action == "modified" {
HandleBlock(path.Path)
handleCommit(path.Path)
handleVersion(path.Path)
} else {
HandleBlock(path.Path)
handleCommit(path.Path)
handleVersion(path.Path)
}
}
}
Expand Down
Loading

0 comments on commit 523373a

Please sign in to comment.