-
Notifications
You must be signed in to change notification settings - Fork 1
/
set-current-project
executable file
·181 lines (163 loc) · 5.3 KB
/
set-current-project
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/usr/bin/env ruby
#
# Set the current project, so you can auto cd to that folder when you
# open a new terminal. Also sets up some handy aliases to jump into
# the current project's databases: if the project folder has a
# config/database.yml file in it, then for each environment defined
# inside, a db* alias (e.g. db_development, db_test) will be created.
# (Currently only supports mysql and psql.)
#
# set-current-project [<path>]
#
# If path is omitted, uses current folder.
#
# This will set a ./current-project file in your home folder and
# export CURRENT_PROJECT into your environment. With the appropriate
# code in your profile, this will automatically cd you into the
# project folder as soon as you login.
#
# Add this to the end of your .profile or
# .bashrc:
#
# if [[ -s ~/.current-project ]] ; then
# source ~/.current-project
# fi
#
# Notes:
#
# * You can clear the current project by deleting the file, or running
# unset-current-project (which just deletes the file)
#
# * I think aliases like db_development are cleaner and easier to read
# than aliases like dbdevelopment, but dbd<TAB> is a LOT easier to
# type, so that's why.
require 'yaml'
$known_databases = {
"psql" => {
"adapter" => /postgresql/,
"command" => "psql",
# psql does not accept password at command line. Sorry.
"short_switches" => { "username" => "U", "host" => "h", "port" => "p" },
"long_switches" => { },
"args" => ["database"]
},
"postgresql" => {
"adapter" => /postgresql/,
"command" => "psql",
# psql does not accept password at command line. Sorry.
"short_switches" => { "username" => "U", "host" => "h", "port" => "p" },
"long_switches" => { },
"args" => ["database"]
},
"postgis" => {
"adapter" => /postgis/,
"command" => "psql",
# psql does not accept password at command line. Sorry.
"short_switches" => { "username" => "U", "host" => "h", "port" => "p" },
"long_switches" => { },
"args" => ["database"]
},
"mysql" => {
"adapter" => /mysql(2)?/,
"command" => "mysql",
"short_switches" => { "username" => "u", "host" => "h", "port" => "P" },
"long_switches" => { "password" => "password" },
"args" => ["database"]
},
"sqlite3" => {
"adapter" => /sqlite3/,
"command" => "sqlite3",
"short_switches" => {},
"long_switches" => {},
"args" => ["database"]
}
}
args = ARGV.dup
include_aliases = true
if args.include?("--quick") || args.include?("-q")
args.delete("--quick")
args.delete("-q")
include_aliases = false
end
target = if args.empty?
Dir.pwd
else
args.first
end
def fetch_adapter(adapter)
adapter = $known_databases.detect {|name, data| adapter =~ data["adapter"]}
adapter = adapter.last if adapter
end
def recognized_adapter?(env)
fetch_adapter env["adapter"]
end
def build_config_aliases(config, prefix='')
aliases = []
Array(config).each do |name, env|
next unless env.key?("database") && env.key?("adapter")
next if name == 'default'
if !recognized_adapter?(env)
puts "Skipping environment #{env} because adapter #{fetch_adapter env['adapter']} was unrecognized"
next
end
adapter = fetch_adapter env["adapter"]
command = "%s %s %s %s" % [adapter["command"],
adapter["short_switches"].map {|env_key, switch| '-%s "%s"' % [switch, env[env_key]] if env[env_key]}.compact.join(' '),
adapter["long_switches"].map {|env_key, switch| '--%s="%s"' % [switch, env[env_key]] if env[env_key]}.compact.join(' '),
adapter["args"].map {|env_key| env[env_key]}.compact.join(' ')]
command = command.gsub(/\s+/, ' ').strip
aliases << "alias 'db%s%s'='%s'" % [prefix, name, command]
end
aliases
end
def cdp_alias
%q(alias 'cdp'="cd \\"$CURRENT_PROJECT\\"")
end
def build_command_aliases
aliases = []
aliases << cdp_alias
aliases
end
# some projects have multiple databases, configured with files like
# database_history.yml; capture these with a prefix so e.g. dbh<TAB>t<TAB> will
# expand to alias dbhistorytest, etc.
def config_filename_prefix(config_filename)
regex = %r|database_?([^/]*).yml|
prefix = config_filename.match(regex)[1]
puts "#{config_filename.inspect} => #{prefix.inspect}"
prefix
end
aliases = []
if include_aliases
Dir.glob(File.join(target, 'config/database*.yml')).each do |config_file|
if File.exist? config_file
# Don't use YAML.load_file, Syck barfs when the yaml file lacks \n at EOF
output = File.read(config_file)
config = YAML.load(output, aliases: true)
prefix = config_filename_prefix(config_file)
aliases += build_config_aliases config, prefix
end
end
aliases += build_command_aliases
puts '-' * 80
puts "Command aliases:"
puts aliases
puts '-' * 80
else
aliases = Array(cdp_alias)
end
File.open(File.expand_path("~/.current-project"), "w") do |file|
file.puts <<EOF
CURRENT_PROJECT="#{target}"
cd "$CURRENT_PROJECT"
# Path
if [[ -e "$CURRENT_PROJECT/script" ]] ; then
export PATH=$PATH:"$CURRENT_PROJECT/script"
fi
# Aliases:
#{aliases * "\n"}
EOF
end
puts "Current project has been set to #{target}. You will automatically cd to this folder on login."
puts "If plan to keep working this terminal session, you should run:"
puts "\e[1;37;40msource ~/.current-project\e[0m"