label_weaver 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +3 -0
- data/exe/label_weaver +7 -0
- data/label_weaver.gemspec +38 -0
- data/lib/label_weaver/cli/actions/develop/start.rb +65 -0
- data/lib/label_weaver/cli/actions/develop/stop.rb +77 -0
- data/lib/label_weaver/cli/actions/diff/file.rb +19 -0
- data/lib/label_weaver/cli/actions/diff/format.rb +19 -0
- data/lib/label_weaver/cli/actions/init.rb +48 -0
- data/lib/label_weaver/cli/actions/prepare_base_project.rb +30 -0
- data/lib/label_weaver/cli/commands/develop.rb +16 -0
- data/lib/label_weaver/cli/commands/diff.rb +69 -0
- data/lib/label_weaver/cli/shell.rb +50 -0
- data/lib/label_weaver/configuration/contract.rb +15 -0
- data/lib/label_weaver/configuration/defaults.yml +12 -0
- data/lib/label_weaver/configuration/model.rb +12 -0
- data/lib/label_weaver/container.rb +30 -0
- data/lib/label_weaver/import.rb +7 -0
- data/lib/label_weaver/temp_repo.rb +111 -0
- data/lib/label_weaver.rb +18 -0
- metadata +276 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8d4577814ad253da907628f3c86300dc89c2b362260fa6772af602670ce2aa63
|
4
|
+
data.tar.gz: a262362d186dca07c7789baca7cd642c3d9b43e5ea1ca3ec6259ac4a244ef90f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 64c146c67e07cb609d4c7ac458e37d071edd0e592ec460f3b692b559a5121b2dfa12c5294a71eb565cb7d2064d54053aae8a0cf09ccdae2fc94fe48f4970cbcd
|
7
|
+
data.tar.gz: 17f74363825bd9115228468d77b175b19c2895a680acd3809e0a7d25f3dda1338cae90e660fd26140fc57b78cd6aff80dd99f405938141d46cfcb5d56104d131
|
data/README.md
ADDED
data/exe/label_weaver
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "label_weaver"
|
5
|
+
spec.version = "0.0.3"
|
6
|
+
spec.authors = ["Stefan Exner"]
|
7
|
+
spec.email = ["stex@stex.codes"]
|
8
|
+
spec.homepage = "https://gitlab.com/lopo-tech/label_weaver"
|
9
|
+
spec.summary = "Helper tool to manage whitelabel version of base projects"
|
10
|
+
spec.license = "MIT"
|
11
|
+
|
12
|
+
spec.metadata = {
|
13
|
+
"label" => "LabelWeaver",
|
14
|
+
"rubygems_mfa_required" => "true"
|
15
|
+
}
|
16
|
+
|
17
|
+
spec.required_ruby_version = "~> 3.3"
|
18
|
+
spec.add_dependency "cogger", "~> 0.21"
|
19
|
+
spec.add_dependency "containable", "~> 0.0"
|
20
|
+
spec.add_dependency "dry-monads", "~> 1.6"
|
21
|
+
spec.add_dependency "dry-schema", "~> 1.6"
|
22
|
+
spec.add_dependency "diffy", "~> 3.4"
|
23
|
+
spec.add_dependency "etcher", "~> 1.6"
|
24
|
+
spec.add_dependency "git", "~> 2.1.1"
|
25
|
+
spec.add_dependency "infusible", "~> 3.5"
|
26
|
+
spec.add_dependency "ruby-next-core", "~> 1.0"
|
27
|
+
spec.add_dependency "runcom", "~> 11.0"
|
28
|
+
spec.add_dependency "sod", "~> 0.8"
|
29
|
+
spec.add_dependency "spek", "~> 3.0"
|
30
|
+
spec.add_dependency "tty-file", "~> 0.10"
|
31
|
+
spec.add_dependency "tty-pager", "~> 0.14"
|
32
|
+
spec.add_dependency "zeitwerk", "~> 2.6"
|
33
|
+
|
34
|
+
spec.bindir = "exe"
|
35
|
+
spec.executables << "label_weaver"
|
36
|
+
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
|
37
|
+
spec.files = Dir["*.gemspec", "lib/**/*"]
|
38
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "git"
|
2
|
+
require "yaml"
|
3
|
+
require "digest"
|
4
|
+
|
5
|
+
module LabelWeaver
|
6
|
+
module CLI
|
7
|
+
module Actions
|
8
|
+
module Develop
|
9
|
+
class Start < Sod::Action
|
10
|
+
include Import[:kernel, :configuration, :xdg_config, :logger]
|
11
|
+
|
12
|
+
using Refinements::Pathname
|
13
|
+
|
14
|
+
description "Starts whitelabel development mode"
|
15
|
+
ancillary "Fetches the latest git changes and syncs them with your local branch."
|
16
|
+
|
17
|
+
on %w[--start]
|
18
|
+
|
19
|
+
def call(*args)
|
20
|
+
unless xdg_config.active
|
21
|
+
logger.error("No configuration found. Are you in the correct directory?")
|
22
|
+
kernel.exit(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
repo.clone_or_update
|
26
|
+
copy_repository_files
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def copy_repository_files
|
32
|
+
logger.info "Copying repository files to whitelabel project..."
|
33
|
+
|
34
|
+
repo.relevant_files.each do |repository_file|
|
35
|
+
relative_filename = repo.relative_path(repository_file)
|
36
|
+
project_file = context.project_root_dir + relative_filename
|
37
|
+
|
38
|
+
if project_file.exist?
|
39
|
+
if repo.timestamp_for(repository_file) > project_file.mtime
|
40
|
+
logger.warn "File '#{relative_filename}' has a newer version in the remote repository (#{repo.timestamp_for(repository_file)} vs #{project_file.mtime})."
|
41
|
+
end
|
42
|
+
|
43
|
+
logger.debug "Skipping '#{relative_filename}'..."
|
44
|
+
next
|
45
|
+
end
|
46
|
+
|
47
|
+
FileUtils.mkdir_p(project_file.dirname)
|
48
|
+
FileUtils.copy(repository_file, project_file, preserve: true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def repo
|
53
|
+
@repo ||= LabelWeaver::TempRepo.new(
|
54
|
+
context.repository_dir,
|
55
|
+
repository_url: configuration.git_repository,
|
56
|
+
branch: configuration.git_branch,
|
57
|
+
excludes: configuration.excludes,
|
58
|
+
logger: logger
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "git"
|
2
|
+
require "yaml"
|
3
|
+
require "digest"
|
4
|
+
|
5
|
+
module LabelWeaver
|
6
|
+
module CLI
|
7
|
+
module Actions
|
8
|
+
module Develop
|
9
|
+
class Stop < Sod::Action
|
10
|
+
include Import[:configuration, :xdg_config, :kernel, :logger]
|
11
|
+
|
12
|
+
using Refinements::Pathname
|
13
|
+
|
14
|
+
description "Stops whitelabel development mode"
|
15
|
+
ancillary "Removes all unchanged files from the whitelabel project again."
|
16
|
+
|
17
|
+
on %w[--stop]
|
18
|
+
|
19
|
+
def call(*args)
|
20
|
+
unless xdg_config.active
|
21
|
+
logger.error("No configuration found. Are you in the correct directory?")
|
22
|
+
kernel.exit(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
remove_base_files
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def remove_base_files
|
31
|
+
logger.info "Removing unchanged base files from whitelabel project"
|
32
|
+
|
33
|
+
repo.relevant_files.each do |repository_file|
|
34
|
+
relative_filename = repo.relative_path(repository_file)
|
35
|
+
project_file = context.project_root_dir + relative_filename
|
36
|
+
|
37
|
+
if project_file.exist?
|
38
|
+
# TODO: Should we get a time component in here to check for possible newer base repo files?
|
39
|
+
if digest(project_file) != digest(repository_file)
|
40
|
+
logger.info "File '#{relative_filename}' is kept as it was changed in the whitelabel project (r: #{repo.timestamp_for(repository_file)} vs w: #{project_file.mtime})."
|
41
|
+
else
|
42
|
+
logger.debug "Deleting file '#{relative_filename}'..."
|
43
|
+
project_file.unlink
|
44
|
+
|
45
|
+
remove_empty_tree(project_file.dirname)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def remove_empty_tree(dir)
|
52
|
+
return unless dir.empty?
|
53
|
+
|
54
|
+
logger.debug "Deleting empty directory '#{dir}'..."
|
55
|
+
dir.unlink
|
56
|
+
|
57
|
+
remove_empty_tree(dir.parent)
|
58
|
+
end
|
59
|
+
|
60
|
+
def digest(file)
|
61
|
+
Digest::SHA1.file(file).hexdigest
|
62
|
+
end
|
63
|
+
|
64
|
+
def repo
|
65
|
+
@repo ||= LabelWeaver::TempRepo.new(
|
66
|
+
context.repository_dir,
|
67
|
+
repository_url: configuration.git_repository,
|
68
|
+
branch: configuration.git_branch,
|
69
|
+
excludes: configuration.excludes,
|
70
|
+
logger: logger
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LabelWeaver
|
2
|
+
module CLI
|
3
|
+
module Actions
|
4
|
+
module Diff
|
5
|
+
class File < Sod::Action
|
6
|
+
using Refinements::Pathname
|
7
|
+
|
8
|
+
description "Shows a diff for a single chosen file. Expects a path relative to the project root."
|
9
|
+
|
10
|
+
on %w[-f --file], argument: "PATH", type: String
|
11
|
+
|
12
|
+
def call(path)
|
13
|
+
context.input[:file] = Pathname.new(path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LabelWeaver
|
2
|
+
module CLI
|
3
|
+
module Actions
|
4
|
+
module Diff
|
5
|
+
class Format < Sod::Action
|
6
|
+
using Refinements::Pathname
|
7
|
+
|
8
|
+
description "Choose the format to be used when displaying the diff."
|
9
|
+
|
10
|
+
on %w[--format], argument: "FORMAT", type: String, allow: %w[unified patch]
|
11
|
+
|
12
|
+
def call(diff_format)
|
13
|
+
context.input[:format] = diff_format
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "tty/file"
|
2
|
+
|
3
|
+
module LabelWeaver
|
4
|
+
module CLI
|
5
|
+
module Actions
|
6
|
+
class Init < Sod::Action
|
7
|
+
include Import[:kernel, :logger]
|
8
|
+
|
9
|
+
using Refinements::Pathname
|
10
|
+
|
11
|
+
on "--init"
|
12
|
+
|
13
|
+
description "Initializes a new whitelabel project"
|
14
|
+
|
15
|
+
def call(*)
|
16
|
+
create_config
|
17
|
+
create_gitignore
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def create_config
|
23
|
+
xdg_config = context[xdg_config, :xdg_config]
|
24
|
+
defaults_path = Pathname.new(context[defaults_path, :defaults_path])
|
25
|
+
|
26
|
+
path = xdg_config.local
|
27
|
+
path_info = path.to_s.inspect
|
28
|
+
|
29
|
+
if path.exist?
|
30
|
+
logger.warn { "Skipped. Configuration exists: #{path_info}." }
|
31
|
+
else
|
32
|
+
defaults_path.copy path.make_ancestors
|
33
|
+
logger.info { "Created: #{path_info}." }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_gitignore
|
38
|
+
TTY::File.create_file(gitignore)
|
39
|
+
TTY::File.append_to_file(gitignore, "repository", force: false)
|
40
|
+
end
|
41
|
+
|
42
|
+
def gitignore
|
43
|
+
context.local_tmp_dir + ".gitignore"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "tty/file"
|
2
|
+
|
3
|
+
module LabelWeaver
|
4
|
+
module CLI
|
5
|
+
module Actions
|
6
|
+
class PrepareBaseProject < Sod::Action
|
7
|
+
include Import[:kernel, :logger]
|
8
|
+
|
9
|
+
on "--prepare-base-project"
|
10
|
+
|
11
|
+
description "Adjusts certain files in a project to be used as base for whitelabel projects."
|
12
|
+
|
13
|
+
def call(*)
|
14
|
+
adjust_dockerignore
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def adjust_dockerignore
|
20
|
+
TTY::File.create_file(dockerignore) unless dockerignore.exist?
|
21
|
+
TTY::File.append_to_file(dockerignore, ".config/label_weaver")
|
22
|
+
end
|
23
|
+
|
24
|
+
def dockerignore
|
25
|
+
context.project_root_dir + ".dockerignore"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module LabelWeaver
|
2
|
+
module CLI
|
3
|
+
module Commands
|
4
|
+
class Develop < Sod::Command
|
5
|
+
include Import[:kernel, :logger]
|
6
|
+
|
7
|
+
handle "develop"
|
8
|
+
|
9
|
+
description "Start / Stop whitelabel development mode"
|
10
|
+
|
11
|
+
on(::LabelWeaver::CLI::Actions::Develop::Start)
|
12
|
+
on(::LabelWeaver::CLI::Actions::Develop::Stop)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "tty/pager"
|
2
|
+
require "diffy"
|
3
|
+
|
4
|
+
module LabelWeaver
|
5
|
+
module CLI
|
6
|
+
module Commands
|
7
|
+
class Diff < Sod::Command
|
8
|
+
include Import[:kernel, :logger, :configuration]
|
9
|
+
|
10
|
+
handle "diff"
|
11
|
+
|
12
|
+
description "Shows difference between the base repository and the local files "
|
13
|
+
|
14
|
+
on(::LabelWeaver::CLI::Actions::Diff::Format)
|
15
|
+
on(::LabelWeaver::CLI::Actions::Diff::File)
|
16
|
+
|
17
|
+
def call(*)
|
18
|
+
@file_path = context.input[:file]
|
19
|
+
|
20
|
+
case context.input[:format] || "unified"
|
21
|
+
when "unified"
|
22
|
+
TTY::Pager.page do |pager|
|
23
|
+
changed_files.each do |repository_file, project_file|
|
24
|
+
pager.write <<~EOS
|
25
|
+
|
26
|
+
#{"*" * (project_file.to_s.length + 4)}
|
27
|
+
* #{project_file} *
|
28
|
+
#{"*" * (project_file.to_s.length + 4)}
|
29
|
+
|
30
|
+
EOS
|
31
|
+
|
32
|
+
pager.write Diffy::Diff.new(repository_file.to_s, project_file.to_s, source: "files", context: 3).to_s(:color)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
when "patch"
|
36
|
+
changed_files.each do |repository_file, project_file|
|
37
|
+
puts Diffy::Diff.new(repository_file.to_s, project_file.to_s, source: "files", context: 0, include_diff_info: true)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
logger.error "Unknown format: #{context.input[:format]}"
|
41
|
+
end
|
42
|
+
logger.info context.input.inspect
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def changed_files
|
48
|
+
repo.relevant_files_with_project_files(project_root_dir: context.project_root_dir).filter_map do |repository_file, project_file|
|
49
|
+
next unless project_file.exist?
|
50
|
+
next unless repo.changed_file?(repository_file, project_root_dir: context.project_root_dir)
|
51
|
+
next if @file_path && project_file != context.project_root_dir + @file_path
|
52
|
+
|
53
|
+
[repository_file, project_file]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def repo
|
58
|
+
@repo ||= LabelWeaver::TempRepo.new(
|
59
|
+
context.repository_dir,
|
60
|
+
repository_url: configuration.git_repository,
|
61
|
+
branch: configuration.git_branch,
|
62
|
+
excludes: configuration.excludes,
|
63
|
+
logger: logger
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "sod"
|
4
|
+
|
5
|
+
module LabelWeaver
|
6
|
+
module CLI
|
7
|
+
# The main Command Line Interface (CLI) object.
|
8
|
+
class Shell
|
9
|
+
include Import[:defaults_path, :xdg_config, :specification]
|
10
|
+
|
11
|
+
def initialize(context: Sod::Context, dsl: Sod, **)
|
12
|
+
super(**)
|
13
|
+
@context = context
|
14
|
+
@dsl = dsl
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(...) = cli.call(...)
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :context, :dsl
|
22
|
+
|
23
|
+
def cli
|
24
|
+
context = build_context
|
25
|
+
|
26
|
+
dsl.new :label_weaver, banner: specification.banner do
|
27
|
+
on(::LabelWeaver::CLI::Actions::Init, context:)
|
28
|
+
on(::LabelWeaver::CLI::Actions::PrepareBaseProject, context:)
|
29
|
+
on(::LabelWeaver::CLI::Commands::Develop, context:)
|
30
|
+
on(::LabelWeaver::CLI::Commands::Diff, context:)
|
31
|
+
on(Sod::Prefabs::Actions::Version, context:)
|
32
|
+
on(Sod::Prefabs::Actions::Help, self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_context
|
37
|
+
context[
|
38
|
+
input: {},
|
39
|
+
project_root_dir: Pathname.new(Dir.pwd),
|
40
|
+
local_tmp_dir: Pathname.new(Dir.pwd).join(".config", "label_weaver"),
|
41
|
+
repository_dir: Pathname.new(Dir.pwd).join(".config", "label_weaver", "repository"),
|
42
|
+
tracking_file: Pathname.new(Dir.pwd).join(".config", "label_weaver", "files.yml"),
|
43
|
+
defaults_path:,
|
44
|
+
xdg_config:,
|
45
|
+
version_label: specification.labeled_version
|
46
|
+
]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/schema"
|
4
|
+
|
5
|
+
Dry::Schema.load_extensions :monads
|
6
|
+
|
7
|
+
module LabelWeaver
|
8
|
+
module Configuration
|
9
|
+
Contract = Dry::Schema.Params do
|
10
|
+
required(:git_repository).filled :string
|
11
|
+
required(:git_branch).filled :string
|
12
|
+
optional(:excludes).array :string
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
git:
|
2
|
+
repository: "git@gitlab.com:lopo-tech/label_weaver.git"
|
3
|
+
branch: "main"
|
4
|
+
# Files to exclude from the base repository, they will not be copied over to the whitelabel project.
|
5
|
+
# Shell filename globbing rules apply, not regular expressions
|
6
|
+
excludes:
|
7
|
+
- .git/**
|
8
|
+
# Files here will be appended on whitelabel development instead of being skipped if the
|
9
|
+
# file already exists in a project
|
10
|
+
#append:
|
11
|
+
# - .gitignore
|
12
|
+
# - .dockerignore
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cogger"
|
4
|
+
require "containable"
|
5
|
+
require "etcher"
|
6
|
+
require "runcom"
|
7
|
+
require "spek"
|
8
|
+
|
9
|
+
module LabelWeaver
|
10
|
+
# Provides a global gem container for injection into other objects.
|
11
|
+
module Container
|
12
|
+
extend Containable
|
13
|
+
|
14
|
+
register :configuration do
|
15
|
+
self[:defaults].add_loader(:yaml, self[:xdg_config].active)
|
16
|
+
.then { |registry| Etcher.call registry }
|
17
|
+
end
|
18
|
+
|
19
|
+
register :defaults do
|
20
|
+
Etcher::Registry.new(contract: Configuration::Contract, model: Configuration::Model)
|
21
|
+
.add_loader(:yaml, self[:defaults_path])
|
22
|
+
end
|
23
|
+
|
24
|
+
register(:specification) { Spek::Loader.call "#{__dir__}/../../label_weaver.gemspec" }
|
25
|
+
register(:defaults_path) { Pathname(__dir__).join("configuration/defaults.yml") }
|
26
|
+
register(:xdg_config) { Runcom::Config.new("label_weaver/configuration.yml") }
|
27
|
+
register(:logger) { Cogger.new(id: "label_weaver") }
|
28
|
+
register :kernel, Kernel
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "git"
|
4
|
+
require "digest"
|
5
|
+
|
6
|
+
module LabelWeaver
|
7
|
+
class TempRepo
|
8
|
+
using Refinements::Pathname
|
9
|
+
|
10
|
+
attr_reader :repository_path, :repository_url, :branch, :excludes, :logger
|
11
|
+
|
12
|
+
def initialize(repository_path, repository_url:, branch: "main", excludes: [], logger: Logger.new($stdout))
|
13
|
+
@repository_path = repository_path
|
14
|
+
@repository_url = repository_url
|
15
|
+
@branch = branch
|
16
|
+
@excludes = excludes + %w[. ..]
|
17
|
+
@logger = logger
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# @return [Time] the last time the file was part of a commit, closest we can get to an mtime
|
22
|
+
#
|
23
|
+
def timestamp_for(file)
|
24
|
+
repo.log(1).path(file).first.date
|
25
|
+
end
|
26
|
+
|
27
|
+
def digest_for(file)
|
28
|
+
Digest::SHA1.file(file).hexdigest
|
29
|
+
end
|
30
|
+
|
31
|
+
def changed_file?(repository_file, project_root_dir:)
|
32
|
+
digest_for(repository_file) != digest_for(project_root_dir + relative_path(repository_file))
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Clones the repository if it doesn't exist yet locally or fetches the latest updates
|
37
|
+
#
|
38
|
+
def clone_or_update
|
39
|
+
if repository_path.exist?
|
40
|
+
logger.info "Pulling latest changes from remote repository (#{repository_url})..."
|
41
|
+
|
42
|
+
repo.pull("origin", branch)
|
43
|
+
else
|
44
|
+
logger.info "Cloning remote repository, this might take a while..."
|
45
|
+
|
46
|
+
Git.clone(
|
47
|
+
repository_url,
|
48
|
+
repository_path.basename,
|
49
|
+
path: repository_path.parent,
|
50
|
+
branch:
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# @return [Array<Pathname>] All repository files that are not set to be excluded
|
57
|
+
#
|
58
|
+
def relevant_files
|
59
|
+
files.filter do |file|
|
60
|
+
# Reject any files that are set up to be excluded. Shell filename globbing rules apply
|
61
|
+
next false if excludes.any? { relative_path(file).fnmatch?(_1, File::FNM_DOTMATCH) }
|
62
|
+
|
63
|
+
true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Updates the atime and mtime of each file in the repository to their latest commit time
|
69
|
+
# TODO: Check if still needed
|
70
|
+
#
|
71
|
+
def update_repository_timestamps
|
72
|
+
logger.info "Updating repository timestamps..."
|
73
|
+
repository_path.glob("**/*", File::FNM_DOTMATCH).each do |file|
|
74
|
+
# Set the file modification times to the last time they were updated in a commit
|
75
|
+
time = repo.all.log.path(file).first.date
|
76
|
+
file.utime(time, time)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# @return [Pathname] the filename relative to the git repository root
|
82
|
+
#
|
83
|
+
def relative_path(filename)
|
84
|
+
filename.relative_path_from(repository_path)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# @return [Array<Array<Pathname, Pathname>>] all relevant repository files with their corresponding
|
89
|
+
# path within the project
|
90
|
+
#
|
91
|
+
def relevant_files_with_project_files(project_root_dir:)
|
92
|
+
relevant_files.map do |repository_file|
|
93
|
+
relative_filename = relative_path(repository_file)
|
94
|
+
[repository_file, project_root_dir + relative_filename]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
#
|
101
|
+
# @return [Array<Pathname>] All files inside the repository, including dotfiles. No folders.
|
102
|
+
#
|
103
|
+
def files
|
104
|
+
repository_path.glob("**/*", File::FNM_DOTMATCH).select(&:file?)
|
105
|
+
end
|
106
|
+
|
107
|
+
def repo
|
108
|
+
@repo ||= Git.open(repository_path)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/label_weaver.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
require "ruby-next"
|
5
|
+
|
6
|
+
Zeitwerk::Loader.new.then do |loader|
|
7
|
+
loader.inflector.inflect "cli" => "CLI"
|
8
|
+
loader.tag = File.basename __FILE__, ".rb"
|
9
|
+
loader.push_dir __dir__
|
10
|
+
loader.setup
|
11
|
+
end
|
12
|
+
|
13
|
+
# Main namespace.
|
14
|
+
module LabelWeaver
|
15
|
+
def self.loader(registry = Zeitwerk::Registry)
|
16
|
+
@loader ||= registry.loaders.find { |loader| loader.tag == File.basename(__FILE__, ".rb") }
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: label_weaver
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stefan Exner
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-08-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cogger
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.21'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.21'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: containable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-monads
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dry-schema
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: diffy
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.4'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: etcher
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.6'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: git
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.1.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.1.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: infusible
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.5'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.5'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: ruby-next-core
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: runcom
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '11.0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '11.0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: sod
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0.8'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0.8'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: spek
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '3.0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '3.0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: tty-file
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0.10'
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0.10'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: tty-pager
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0.14'
|
202
|
+
type: :runtime
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0.14'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: zeitwerk
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - "~>"
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '2.6'
|
216
|
+
type: :runtime
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - "~>"
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '2.6'
|
223
|
+
description:
|
224
|
+
email:
|
225
|
+
- stex@stex.codes
|
226
|
+
executables:
|
227
|
+
- label_weaver
|
228
|
+
extensions: []
|
229
|
+
extra_rdoc_files:
|
230
|
+
- README.md
|
231
|
+
files:
|
232
|
+
- README.md
|
233
|
+
- exe/label_weaver
|
234
|
+
- label_weaver.gemspec
|
235
|
+
- lib/label_weaver.rb
|
236
|
+
- lib/label_weaver/cli/actions/develop/start.rb
|
237
|
+
- lib/label_weaver/cli/actions/develop/stop.rb
|
238
|
+
- lib/label_weaver/cli/actions/diff/file.rb
|
239
|
+
- lib/label_weaver/cli/actions/diff/format.rb
|
240
|
+
- lib/label_weaver/cli/actions/init.rb
|
241
|
+
- lib/label_weaver/cli/actions/prepare_base_project.rb
|
242
|
+
- lib/label_weaver/cli/commands/develop.rb
|
243
|
+
- lib/label_weaver/cli/commands/diff.rb
|
244
|
+
- lib/label_weaver/cli/shell.rb
|
245
|
+
- lib/label_weaver/configuration/contract.rb
|
246
|
+
- lib/label_weaver/configuration/defaults.yml
|
247
|
+
- lib/label_weaver/configuration/model.rb
|
248
|
+
- lib/label_weaver/container.rb
|
249
|
+
- lib/label_weaver/import.rb
|
250
|
+
- lib/label_weaver/temp_repo.rb
|
251
|
+
homepage: https://gitlab.com/lopo-tech/label_weaver
|
252
|
+
licenses:
|
253
|
+
- MIT
|
254
|
+
metadata:
|
255
|
+
label: LabelWeaver
|
256
|
+
rubygems_mfa_required: 'true'
|
257
|
+
post_install_message:
|
258
|
+
rdoc_options: []
|
259
|
+
require_paths:
|
260
|
+
- lib
|
261
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
262
|
+
requirements:
|
263
|
+
- - "~>"
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: '3.3'
|
266
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
|
+
requirements:
|
268
|
+
- - ">="
|
269
|
+
- !ruby/object:Gem::Version
|
270
|
+
version: '0'
|
271
|
+
requirements: []
|
272
|
+
rubygems_version: 3.5.14
|
273
|
+
signing_key:
|
274
|
+
specification_version: 4
|
275
|
+
summary: Helper tool to manage whitelabel version of base projects
|
276
|
+
test_files: []
|