devlogs 0.1.4 → 0.2.0
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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +12 -5
- data/exe/devlogs +1 -1
- data/lib/devlogs/cli.rb +79 -0
- data/lib/devlogs/editor.rb +24 -0
- data/lib/devlogs/repository.rb +59 -11
- data/lib/devlogs/version.rb +1 -1
- data/lib/devlogs.rb +1 -54
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ee70029616eb23078cfe60734052a855642617338f776543da002c18986cfad
|
4
|
+
data.tar.gz: 8169a90b74e0524f6b9b0ebdb786ff0fb1df38e8d59c7d6bbdbbce7936d037d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3aba32f26e6905b876ad6e0777a86d29abfe1ea0642180fe1320ee82b20cc3a8efd2e22088d3b469149f920fa12808166ee7572b1f2207337afbf146bbac38cc
|
7
|
+
data.tar.gz: 9fa406dae78b034c22c9db6f992e00a0255c920bb569f68fb4c5a20a295df8bcab8fad4f7f58f1d8a4f0870e05025f0d7b7c135bd50feea06e5b31ccf5b62fcf
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
# devlogs
|
2
|
-

|
3
|
-
|
4
2
|
Project based session logging for solo-developers with the option to mirror changes to another directory.
|
5
3
|
|
6
4
|
https://stacktrace.one/blog/avoid-project-management-solo-dev/
|
@@ -25,12 +23,12 @@ Or install it yourself as:
|
|
25
23
|
|
26
24
|
## Usage
|
27
25
|
### Initialize
|
28
|
-
Inside your project initialize the `
|
26
|
+
Inside your project initialize the `_devlogs` repository:
|
29
27
|
```bash
|
30
28
|
$ devlogs init
|
31
29
|
```
|
32
30
|
|
33
|
-
Follow the prompts to setup the project configuration located in `
|
31
|
+
Follow the prompts to setup the project configuration located in `_devlogs/.devlogs.config`.
|
34
32
|
|
35
33
|
You can setup a mirror directory path in the configuration stage to sync changes to another directory on your machine, for example to Obsidian.md.
|
36
34
|
|
@@ -38,7 +36,7 @@ Example:
|
|
38
36
|
|
39
37
|
```
|
40
38
|
myproject
|
41
|
-
|
39
|
+
_devlogs
|
42
40
|
>> content
|
43
41
|
```
|
44
42
|
|
@@ -68,6 +66,15 @@ Your editor will pop up and you can fill in cliff notes.
|
|
68
66
|
|
69
67
|
Save and if you set a mirror it will sync over!
|
70
68
|
|
69
|
+
### Retrieve previous entry
|
70
|
+
You can use the `last` command to retrieve the most recent entry
|
71
|
+
|
72
|
+
```bash
|
73
|
+
devlogs last
|
74
|
+
```
|
75
|
+
|
76
|
+
The `--open` command will cause the entry to be opened in a new default editor.
|
77
|
+
|
71
78
|
## Development
|
72
79
|
|
73
80
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/exe/devlogs
CHANGED
data/lib/devlogs/cli.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "version"
|
4
|
+
require_relative "repository"
|
5
|
+
require_relative "editor"
|
6
|
+
require "thor"
|
7
|
+
|
8
|
+
module Devlogs
|
9
|
+
#
|
10
|
+
# The CLI devlogs CLI
|
11
|
+
#
|
12
|
+
class CLI < Thor
|
13
|
+
package_name "devlogs"
|
14
|
+
|
15
|
+
# Returns exit with non zero status when an exception occurs
|
16
|
+
def self.exit_on_failure?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Returns version of the cli
|
22
|
+
#
|
23
|
+
desc "version", "Prints the current version"
|
24
|
+
def version
|
25
|
+
puts Devlogs::VERSION
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Initializes a +devlogs+ repository with a configuration
|
30
|
+
#
|
31
|
+
desc "init", "Initialize a developer logs for project"
|
32
|
+
method_options force: :boolean, alias: :string
|
33
|
+
def init
|
34
|
+
puts "Creating devlogs repository"
|
35
|
+
|
36
|
+
Repository::Initialize.run(
|
37
|
+
{ force: options.force? },
|
38
|
+
File.join(".", "_devlogs")
|
39
|
+
)
|
40
|
+
|
41
|
+
puts "Created devlogs"
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Retrieves the most recent entry from the repository
|
46
|
+
#
|
47
|
+
desc "last", "Retrieves the last entry in the repository"
|
48
|
+
method_options open: :boolean, alias: :string
|
49
|
+
def last
|
50
|
+
puts "Reading last entry"
|
51
|
+
last_entry = repo.ls.first
|
52
|
+
|
53
|
+
if options.open?
|
54
|
+
Editor.open(last_entry)
|
55
|
+
else
|
56
|
+
puts File.read(last_entry)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
#
|
60
|
+
# Creates a devlogs entry in the repository and syncs changes
|
61
|
+
# to the mirrored directory if set
|
62
|
+
#
|
63
|
+
desc "entry", "Create a new devlogs entry" # [4]
|
64
|
+
def entry
|
65
|
+
puts "Creating new entry..."
|
66
|
+
repo.create
|
67
|
+
|
68
|
+
repo.sync
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Helper method for repository loading
|
74
|
+
#
|
75
|
+
def repo
|
76
|
+
@repo ||= Repository.load
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Wrapper for terminal editor
|
4
|
+
class Editor
|
5
|
+
def initialize
|
6
|
+
@program = ENV["EDITOR"]
|
7
|
+
end
|
8
|
+
|
9
|
+
# Opens the file contained at the path
|
10
|
+
def open(path)
|
11
|
+
command = "#{@program} #{path}"
|
12
|
+
|
13
|
+
system command
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# Opens the file at +path+ using system editor
|
18
|
+
def open(path)
|
19
|
+
session = new
|
20
|
+
|
21
|
+
session.open(path)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/devlogs/repository.rb
CHANGED
@@ -5,6 +5,8 @@ require "tty-prompt"
|
|
5
5
|
require "yaml"
|
6
6
|
require "rsync"
|
7
7
|
require "pry"
|
8
|
+
require "time"
|
9
|
+
require_relative "editor"
|
8
10
|
|
9
11
|
# Repostiroy is an accessor object for the devlogs directory
|
10
12
|
class Repository
|
@@ -13,20 +15,22 @@ class Repository
|
|
13
15
|
# TODO: should be part of configuration
|
14
16
|
DEFAULT_LOG_SUFFIX = "devlogs.md"
|
15
17
|
DEFAULT_DIRECTORY_PATH = "."
|
16
|
-
DEFAULT_DIRECTORY_NAME = "
|
18
|
+
DEFAULT_DIRECTORY_NAME = "_devlogs"
|
17
19
|
|
18
20
|
# Example: 11-22-2022_1343
|
19
21
|
DEFAULT_TIME_FORMAT_FILE_PREFIX = "%m-%d-%Y__%kh%Mm"
|
20
22
|
DEFAULT_TIME_FORMAT_TEXT_ENTRY = "%m-%d-%Y %k:%M"
|
21
23
|
|
22
|
-
|
24
|
+
VALID_DIRECTION = %i[asc desc].freeze
|
25
|
+
|
26
|
+
# Initializes a _devlogs repository with the supplied configuration
|
23
27
|
# @param repo_config [Repository::Config]
|
24
28
|
#
|
25
29
|
def initialize(repo_config)
|
26
30
|
@config = repo_config
|
27
31
|
end
|
28
32
|
|
29
|
-
# Creates a new
|
33
|
+
# Creates a new _devlogs entry for recording session completion
|
30
34
|
#
|
31
35
|
# @returns nil
|
32
36
|
def create
|
@@ -42,6 +46,7 @@ class Repository
|
|
42
46
|
File.open(entry_file_path, "w") do |f|
|
43
47
|
f.write <<~ENDOFFILE
|
44
48
|
# #{time.strftime(DEFAULT_TIME_FORMAT_TEXT_ENTRY)}
|
49
|
+
Tags: #dev, #log
|
45
50
|
|
46
51
|
What did you do today?
|
47
52
|
|
@@ -49,9 +54,7 @@ class Repository
|
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
52
|
-
|
53
|
-
|
54
|
-
system("#{editor_program} #{entry_file_path}")
|
57
|
+
Editor.open(entry_file_path)
|
55
58
|
|
56
59
|
puts "Writing entry to #{entry_file_path}.."
|
57
60
|
end
|
@@ -66,9 +69,8 @@ class Repository
|
|
66
69
|
|
67
70
|
# Use trailing slash to avoid sub-directory
|
68
71
|
# See rsync manual page
|
69
|
-
path = @config.path[-1] == "/" ? @config.path : @config.path + "/"
|
70
72
|
|
71
|
-
Rsync.run("-av", path, @config.mirror.path) do |result|
|
73
|
+
Rsync.run("-av", @config.path(with_trailing: true), @config.mirror.path) do |result|
|
72
74
|
if result.success?
|
73
75
|
puts "Mirror sync complete."
|
74
76
|
result.changes.each do |change|
|
@@ -81,6 +83,25 @@ class Repository
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
86
|
+
# Lists the files in the repository
|
87
|
+
def ls(direction = :desc)
|
88
|
+
raise ArgumentError, "Must be one of: " + VALID_DIRECTION unless VALID_DIRECTION.include?(direction.to_sym)
|
89
|
+
|
90
|
+
Dir.glob(File.join(@config.path, "*_#{DEFAULT_LOG_SUFFIX}")).sort_by do |fpath|
|
91
|
+
# The date is joined by two underscores to the suffix
|
92
|
+
date, = File.basename(fpath).split("__")
|
93
|
+
|
94
|
+
time_ms = Time.strptime(date, "%m-%d-%Y").to_i
|
95
|
+
|
96
|
+
# Descending
|
97
|
+
if direction == :asc
|
98
|
+
time_ms
|
99
|
+
else
|
100
|
+
-time_ms
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
84
105
|
class << self
|
85
106
|
# Loads a repository from the provided path
|
86
107
|
#
|
@@ -104,15 +125,16 @@ class Repository
|
|
104
125
|
# Config is a configuration data object for storing Repository configuration
|
105
126
|
# in memory for access.
|
106
127
|
class Config
|
107
|
-
attr_reader :name, :description, :mirror, :
|
128
|
+
attr_reader :name, :description, :mirror, :path_value
|
108
129
|
|
130
|
+
# Configuration associated with the Mirror
|
109
131
|
MirrorConfig = Struct.new(:use_mirror, :path, keyword_init: true)
|
110
132
|
|
111
133
|
def initialize(name, desc, mirror, p)
|
112
134
|
@name = name
|
113
135
|
@description = desc
|
114
136
|
@mirror = MirrorConfig.new(mirror)
|
115
|
-
@
|
137
|
+
@path_value = p
|
116
138
|
end
|
117
139
|
|
118
140
|
# Returns whether or not the devlogs repository is configured to mirror
|
@@ -122,6 +144,14 @@ class Repository
|
|
122
144
|
@mirror.use_mirror
|
123
145
|
end
|
124
146
|
|
147
|
+
def path(with_trailing: false)
|
148
|
+
if with_trailing
|
149
|
+
@path_value[-1] == "/" ? @path_value : @path_value + "/"
|
150
|
+
else
|
151
|
+
@path_value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
125
155
|
# Utility method to build a configuration from a Hash
|
126
156
|
#
|
127
157
|
# @returns [Repository::Config]
|
@@ -146,7 +176,11 @@ class Repository
|
|
146
176
|
|
147
177
|
FileUtils.mkdir_p(path)
|
148
178
|
config_file = File.join(path, CONFIG_FILE)
|
149
|
-
|
179
|
+
|
180
|
+
# Replace spaces in project name with underscores
|
181
|
+
sanitized_project_name = results[:name].gsub(/ /, "_").downcase
|
182
|
+
|
183
|
+
info_file_name = "#{sanitized_project_name}_devlogs.info.md"
|
150
184
|
info_file = File.join(path, info_file_name)
|
151
185
|
|
152
186
|
# Create config file
|
@@ -154,10 +188,20 @@ class Repository
|
|
154
188
|
f.write results.to_yaml
|
155
189
|
end
|
156
190
|
|
191
|
+
# Create the info file
|
157
192
|
File.open(info_file, "w") do |f|
|
158
193
|
f.puts "# #{results[:name]}"
|
159
194
|
f.puts (results[:desc]).to_s
|
160
195
|
end
|
196
|
+
|
197
|
+
# Git ignore if specified
|
198
|
+
if results[:gitignore]
|
199
|
+
gitignore = File.join(path, ".gitignore")
|
200
|
+
|
201
|
+
File.open(gitignore, "a") do |f|
|
202
|
+
f.puts DEFAULT_DIRECTORY_NAME
|
203
|
+
end
|
204
|
+
end
|
161
205
|
end
|
162
206
|
|
163
207
|
# Creates an interactive prompt for user input
|
@@ -181,6 +225,10 @@ class Repository
|
|
181
225
|
key(:use_mirror).ask("Do you want to mirror these logs?", convert: :boolean)
|
182
226
|
key(:path).ask("Path to mirror directory: ")
|
183
227
|
end
|
228
|
+
|
229
|
+
key(:gitignore).ask("Do you want to gitignore the devlogs repository?") do |q|
|
230
|
+
q.required true
|
231
|
+
end
|
184
232
|
end
|
185
233
|
end
|
186
234
|
end
|
data/lib/devlogs/version.rb
CHANGED
data/lib/devlogs.rb
CHANGED
@@ -1,56 +1,3 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "devlogs/
|
4
|
-
require_relative "devlogs/repository"
|
5
|
-
|
6
|
-
require "thor"
|
7
|
-
|
8
|
-
module Devlogs
|
9
|
-
#
|
10
|
-
# The CLI devlogs App
|
11
|
-
#
|
12
|
-
class App < Thor
|
13
|
-
package_name "devlogs"
|
14
|
-
|
15
|
-
# Returns exit with non zero status when an exception occurs
|
16
|
-
def self.exit_on_failure?
|
17
|
-
true
|
18
|
-
end
|
19
|
-
|
20
|
-
#
|
21
|
-
# Initializes a +devlogs+ repository with a configuration
|
22
|
-
#
|
23
|
-
desc "init", "Initialize a developer logs for project"
|
24
|
-
method_options force: :boolean, alias: :string
|
25
|
-
def init
|
26
|
-
puts "Creating devlogs repository"
|
27
|
-
|
28
|
-
Repository::Initialize.run(
|
29
|
-
{ force: options.force? },
|
30
|
-
File.join(".", "__devlogs")
|
31
|
-
)
|
32
|
-
|
33
|
-
puts "Created devlogs"
|
34
|
-
end
|
35
|
-
|
36
|
-
#
|
37
|
-
# Creates a devlogs entry in the repository and syncs changes
|
38
|
-
# to the mirrored directory if set
|
39
|
-
#
|
40
|
-
desc "entry", "Create a new devlogs entry" # [4]
|
41
|
-
def entry
|
42
|
-
puts "Creating new entry..."
|
43
|
-
repo.create
|
44
|
-
|
45
|
-
repo.sync
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
# Helper method for repository loading
|
51
|
-
#
|
52
|
-
def repo
|
53
|
-
@repo ||= Repository.load
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
3
|
+
require_relative "devlogs/cli"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devlogs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aquaflamingo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rsync
|
@@ -94,6 +94,8 @@ files:
|
|
94
94
|
- docs/mirroring.png
|
95
95
|
- exe/devlogs
|
96
96
|
- lib/devlogs.rb
|
97
|
+
- lib/devlogs/cli.rb
|
98
|
+
- lib/devlogs/editor.rb
|
97
99
|
- lib/devlogs/repository.rb
|
98
100
|
- lib/devlogs/version.rb
|
99
101
|
homepage: http://github.com/aquaflamingo/devlogs
|
@@ -118,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
120
|
- !ruby/object:Gem::Version
|
119
121
|
version: '0'
|
120
122
|
requirements: []
|
121
|
-
rubygems_version: 3.
|
123
|
+
rubygems_version: 3.3.7
|
122
124
|
signing_key:
|
123
125
|
specification_version: 4
|
124
126
|
summary: A command line utility to create and manage project management with a logs
|