Module: Atk

Defined in:
lib/atk/atk_info.rb,
lib/atk/autocomplete.rb,
lib/atk/commands/project.rb

Defined Under Namespace

Classes: ExecFailed, NoSuchCommand

Constant Summary collapse

@@atk_settings_key =
"atk_settings"

Class Method Summary collapse

Class Method Details

.autocomplete(which_command) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
# File 'lib/atk/autocomplete.rb', line 2

def self.autocomplete(which_command)
    # FUTURE: correct the bugs
    # if which_command == '_'
    #     require_relative './info.rb'
    #     begin
    #         puts Info.commands().keys.map { |each| each.gsub(' ', '\ ') }.join(' ')
    #     rescue => exception
    #         puts ""
    #     end
    # end
end

.checkupObject



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
# File 'lib/atk/atk_info.rb', line 102

def self.checkup
    errors = {}
    
    # make sure ruby is the corrct version
    if VERSION_OF_RUBY >= Version.new("2.6.0")
        errors[:ruby_version_too_high] = true
    elsif VERSION_OF_RUBY < Version.new("2.5")
        errors[:ruby_version_too_low] = true
    end
    
    # make sure git is installed and up to date
    if not Console.has_command("git")
        errors[:doesnt_have_git] = true
    else
        git_version = Version.extract_from(`git --version`)
        if git_version < Version.new("2.17")
            errors[:git_version_too_low] = true
        end
    end
    
    # FUTURE: checkup on the package manager
    
    # FUTURE: verify that windows and unix paths are highest priority
    
    if OS.is?("unix")
        sources = Console.command_sources()
        top_source = sources[0]
        path_for_commands = Atk.paths[:commands]
        if top_source != path_for_commands
            errors[:commands_are_not_at_top_of_path] = true
            if not sources.any?{ |each| each == path_for_commands }
                errors[:commands_are_not_in_path] = true
            end
        end
    end
    
    # 
    # TODO: talk about any found errors
    # 
    if errors.include?[:ruby_version_too_high]
        puts "It looks like your ruby version is too high for ATK"
        puts "some parts of ATK might still work, however expect it to be broken"
    end
end

.infoObject



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/atk/atk_info.rb', line 70

def self.info
    settings_path = Atk.paths[:info]
    # if it doesn't exist then create it
    if not FS.exist?(settings_path)
        FS.write("#{@@atk_settings_key}: {}", to: settings_path)
        return {}
    else
        data = YAML.load_file(settings_path)
        if data.is_a?(Hash)
            if data[@@atk_settings_key].is_a?(Hash)
                return data[@@atk_settings_key]
            end
        end
    end
    return {}
end

.not_yet_implementedObject



185
186
187
# File 'lib/atk/atk_info.rb', line 185

def self.not_yet_implemented()
    puts "Sorry, this feature is still under development"
end

.pathsObject



58
59
60
# File 'lib/atk/atk_info.rb', line 58

def self.paths
    return AtkPaths
end

.project(args) ⇒ Object



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
182
183
# File 'lib/atk/commands/project.rb', line 10

def self.project(args)
    # 
    # no arguments
    # 
    if args.length == 0
        begin
            info = Info.new
        rescue Info::YamlFileDoesntExist => exception
            puts <<-HEREDOC.remove_indent
                
                It appears there is no #{"info.yaml".color_as :code} file
                Meaning you're probably not in folder that contains a project
                
                To convert the current folder into a project folder run:
                    #{"project init".color_as :code}
                
                If you don't know how to use #{"project".color_as :code} just run #{"project help".color_as :code}
            HEREDOC
            exit
        end
        puts "If you don't know how to use #{"project".color_as :code} just run #{"project help".color_as :code}"
        puts ""
        # if there are commands then show them
        commands = info.commands
        if commands.is_a?(Hash) && commands.keys.size > 0
            puts "commands for current project:"
            puts `project commands`
        end
    else
        case args[0]
            # 
            # help
            # 
            when 'help', '--help', '-h'
                puts <<-HEREDOC.remove_indent
                    #{"help".color_as :key_term}
                        #{"info:".color_as :title} displays the avalible tools
                        #{"examples:".color_as :title} #{'project help'.color_as :code}
                    
                    #{"initialize".color_as :key_term}
                        #{"examples:".color_as :title}
                            #{'project init'.color_as :code}
                            #{'project initialize'.color_as :code}
                        #{"info:".color_as :title}
                            This will create an info.yaml in your current directory
                            The info.yaml will contain all the standard project managment tools
                            In the future this command will be more interactive

                    #{"synchronize".color_as :key_term}
                        #{"examples:".color_as :title}
                            #{'project sync'.color_as :code}
                            #{'project synchronize'.color_as :code}
                            #{'project synchronize --message=\'updated the readme\''.color_as :code}
                        #{"info:".color_as :title}
                            Adds, commits, and then pulls/pushes all git changes
                            If there is merge conflict, it will show up as normal
                        #{"format:".color_as :title}
                            #{"project".color_as :code} #{"synchronize".color_as :key_term} #{"<package>".color_as :argument} #{"--message='your message'".color_as :optional}
                    
                    #{"execute".color_as :key_term} 
                        #{"examples:".color_as :title}
                            #{'project execute compile'.color_as :code}
                            #{'project exec compile'.color_as :code}
                            #{'project exec main'.color_as :code}
                            #{'project exec server'.color_as :code}
                        #{"info:".color_as :title}
                            This will look at the info.yaml file in your project to find commands
                            You can use the `project init` command to generate an info.yaml which 
                            has example commands. Commands can be CMD/terminal/console commands, or ruby code.
                        #{"format:".color_as :title}
                            #{"project".color_as :code} #{"execute".color_as :key_term} #{"<name-of-command>".color_as :argument} #{"<arg1-for-command>".color_as :optional} #{"<arg2-for-command>".color_as :optional} #{"<...etc>".color_as :optional}

                    #{"commands".color_as :key_term}
                        #{"examples:".color_as :title} #{'project commands'.color_as :code}
                        #{"info:".color_as :title}
                            This will read the local info.yaml of your project to find commands
                            then it will list out each command with a short preview of the contents of that command
                HEREDOC
            # 
            # init
            # 
            when 'initialize', 'init'
                Info.init
            # 
            # sync
            # 
            when 'synchronize', 'sync'
                # if there is an argument
                git_folder_path = FS.dirname(Info.path)/".git"
                if not FS.is_folder(git_folder_path)
                    raise <<-HEREDOC.remove_indent
                        
                        
                        The `project sync` command was called inside of #{FS.dirname(Info.path)}
                        However, there doesn't seem to be a git repository in this folder
                        (and changes can't be saved/synced without a git repository)
                    HEREDOC
                end
                message = args[1]
                if message == nil
                    message = ""
                else
                    if not message.start_with?('--message=')
                        raise "\n\nWhen giving arguments to the sync command, please give your message as:\n\n    project sync --message='whatever you wanted to say'"
                    else
                        # remove the begining of the message
                        message = args[1].sub(/^--message=/,"")
                        # remove leading/trailing whitespace
                        message.strip!
                    end
                end
                if message.size == 0
                    message = '-'
                end
                
                # add everything
                system('git add -A')
                # commit everything
                system('git', 'commit', '-m', message)
                # pull down everything
                system('git pull --no-edit')
                # push up everything
                system('git push')
            # 
            # execute
            # 
            when 'execute', 'exec'
                # extract the (project_commands) section from the info.yaml, 
                # then find the command with the same name as args[1] and run it
                # FUTURE: use https://github.com/piotrmurach/tty-markdown#ttymarkdown- to highlight the ruby code 
                _, command_name, *command_args = args
                command = Info.commands[command_name]
                # temporairly set the dir to be the same as the info.yaml 
                FS.in_dir(Info.folder()) do
                    if command.is_a?(String)
                        result = system(command+' '+Console.make_arguments_appendable(command_args))
                    elsif command.is_a?(Code)
                        result = command.run(*command_args)
                    elsif command == nil
                        raise NoSuchCommand
                    end
                    
                    # if command resulted in error then raise an error
                    if not result
                        colored_command_name = command_name.color_as :key_term
                        raise ExecFailed, <<-HEREDOC.remove_indent
                            
                            When running: #{"project execute ".color_as :code}#{colored_command_name}
                            The script for #{colored_command_name} hit an error and had an exit code of: #{$?.exitstatus}
                        HEREDOC
                    end
                end
            # 
            # commands
            # 
            when 'commands'
                max_number_of_chars_to_show = 80
                commands = Info.commands
                if commands.keys.size == 0
                    puts "0 avalible commands".color_as :message
                else
                    for each_key, each_value in commands
                        puts "    #{each_key.to_s.color_as :key_term}: #{each_value.to_s.strip[0..max_number_of_chars_to_show].sub(/(.*)[\s\S]*/,'\1')}"
                    end
                end
            # 
            # unrecognized
            # 
            else
                puts "I don't recognized that command\nhere's the `project --help` which might get you what you're looking for:"
                Atk.project(["help"])
        end
    end
end

.run(package_name, arguments = []) ⇒ Object



180
181
182
183
# File 'lib/atk/atk_info.rb', line 180

def self.run(package_name, arguments=[])
    the_package = AtkPackage.new(package_name)
    the_package.run(arguments)
end

.save_info(new_hash) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/atk/atk_info.rb', line 87

def self.save_info(new_hash)
    settings_path = Atk.paths[:info]
    current_settings = Atk.info
    updated_settings = current_settings.merge(new_hash)
    
    info_data = YAML.load_file(Atk.paths[:info])
    if info_file.is_a?(Hash)
        info_data[@@atk_settings_key] = updated_settings
    else
        info_data = { @@atk_settings_key => updated_settings }
    end
    
    FS.save(info_data, to: Atk.paths[:info], as: :yaml )
end

.setup(package_name, arguments) ⇒ Object



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
# File 'lib/atk/atk_info.rb', line 147

def self.setup(package_name, arguments)
    repo_url = AtkPackage.new(package_name).url
    project_folder = Atk.info["project_folder"]
    # if there's no project folder
    if not project_folder
        # then use the current folder
        project_folder = FS.pwd
        puts "Project will be downloaded to #{project_folder.to_s.color_as :key_term}"
        puts "(your current directory)"
        puts ""
    end
    project_name = Console.ask("What do you want to name the project?")
    project_path = project_folder/project_name
    Git.ensure_cloned_and_up_to_date(project_path, repo_url)
    FS.in_dir(project_path) do
        setup_command = Info.commands['(setup)']
        if setup_command.is_a?(Code) || setup_command.is_a?(String)
            puts "\n\n#{"Running (setup) command:".color_as :title}\n"
            sleep 1
            if setup_command.is_a?(Code)
                setup_command.run(arguments)
            else
                system(setup_command + Console.make_arguments_appendable(arguments))
            end
        end
        puts "\n\n\n\n============================================================"
        puts "Finished running setup for: #{project_path.color_as :good}"
        puts "This project has these commands avalible:"
        system "project commands"
        puts "\ndon't forget to do:\n#{"cd '#{project_path}'".color_as :code}"
    end
end

.temp_path(filename) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/atk/atk_info.rb', line 62

def self.temp_path(filename)
    new_path = Atk.paths[:temp]/filename
    # make sure the path is empty
    FS.write("", to: new_path)
    FS.delete(new_path)
    return new_path
end

.update(*args) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/atk/atk_info.rb', line 189

def self.update(*args)
    # 
    # update a specific repo/package
    # 
    if args.size != 0
        Atk.not_yet_implemented()
        return
    end
    
    # 
    # update ATK itself
    #
    puts "Checking latest online version"
    console_output = IO.popen([Atk.paths['gem'], "list", "atk_toolbox", "--remote"]).read
    filtered = console_output.split("\n").select{|each| each =~ /^atk_toolbox \(/}
    latest_version = Version.extract_from(filtered[0])
    # if update avalible
    if Atk.version < latest_version
        puts "Newer version avalible, installing now"
        # install the new gem
        system(Atk.paths['gem'], "install", "atk_toolbox")
        # run the update handler
        temp_file = Atk.temp_path("after_gem_update.rb")
        FS.download("https://raw.githubusercontent.com/aggie-tool-kit/atk-toolbox/master/lib/after_gem_update.rb", to: temp_file)
        system(Atk.paths["ruby"], temp_file, Atk.version.to_s)
    else
        puts "System up to date"
    end
end

.versionObject



52
53
54
55
56
# File 'lib/atk/atk_info.rb', line 52

def self.version
    require_relative '../atk_toolbox/version.rb'
    require_relative './version.rb'
    return Version.new(AtkToolbox::VERSION)
end