feat: implement workspace file tree listing
- Add `list()` method to generate a full workspace file tree - Introduce `WorkspaceItem` and `WorkspaceList` structs - Remove `HeropromptSession` to simplify the public API - Rename Heroscript action to `heropromptworkspace.configure` - Enable full heroscript encoding/decoding for workspaces
This commit is contained in:
@@ -2,25 +2,41 @@
|
||||
|
||||
import freeflowuniverse.herolib.develop.heroprompt
|
||||
|
||||
mut session := heroprompt.new_session()
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import os
|
||||
|
||||
mut workspace1 := session.add_workspace()!
|
||||
// TODO: Check the name bug
|
||||
// mut workspace2 := session.add_workspace(name: 'withname')!
|
||||
|
||||
mut dir1 := workspace1.add_dir(path: '/Users/mahmoud/code/github/freeflowuniverse/herolib/docker')!
|
||||
heroscript_config := '
|
||||
!!heropromptworkspace.configure name:"test workspace" path:"${os.home_dir()}/code/github/freeflowuniverse/herolib"
|
||||
'
|
||||
mut plbook := playbook.new(
|
||||
text: heroscript_config
|
||||
)!
|
||||
|
||||
heroprompt.play(mut plbook)!
|
||||
|
||||
mut workspace1 := heroprompt.new_workspace(
|
||||
path: '${os.home_dir()}/code/github/freeflowuniverse/herolib'
|
||||
)!
|
||||
|
||||
// mut workspace2 := heroprompt.get(
|
||||
// name: 'test workspace'
|
||||
// )!
|
||||
|
||||
mut dir1 := workspace1.add_dir(path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker')!
|
||||
dir1.select_file(name: 'docker_ubuntu_install.sh')!
|
||||
|
||||
mut dir2 := workspace1.add_dir(
|
||||
path: '/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib'
|
||||
path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/herolib'
|
||||
)!
|
||||
|
||||
dir2.select_file(name: '.gitignore')!
|
||||
dir2.select_file(name: 'build.sh')!
|
||||
dir2.select_file(name: 'debug.sh')!
|
||||
file := dir2.select_file(name: 'debug.sh')!
|
||||
// println(file.read()!)
|
||||
|
||||
mut dir3 := workspace1.add_dir(
|
||||
path: '/Users/mahmoud/code/github/freeflowuniverse/herolib/docker/postgresql'
|
||||
path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/postgresql'
|
||||
select_all: true
|
||||
)!
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import os
|
||||
|
||||
|
||||
heroscript_config := '
|
||||
!!heropromptworkspace.configure name:"test workspace" path:"${os.home_dir()}/code/github/freeflowuniverse/herolib"
|
||||
'
|
||||
mut plbook := playbook.new(
|
||||
text: heroscript_config
|
||||
)!
|
||||
|
||||
|
||||
heroprompt.play(mut plbook)!
|
||||
@@ -24,7 +24,7 @@ fn decode_struct[T](_ T, data string) !T {
|
||||
if !data.contains(action_name) {
|
||||
action_name = '${obj_name}.configure'
|
||||
if !data.contains(action_name) {
|
||||
$if debug{
|
||||
$if debug {
|
||||
print_backtrace()
|
||||
}
|
||||
return error('Data does not contain action name: ${obj_name}.define or ${action_name}')
|
||||
@@ -66,11 +66,13 @@ fn decode_struct[T](_ T, data string) !T {
|
||||
}
|
||||
}
|
||||
} $else $if field.is_array {
|
||||
if is_struct_array(typ.$(field.name))! {
|
||||
mut data_fmt := data.replace(action_str, '')
|
||||
data_fmt = data.replace('define.${obj_name}', 'define')
|
||||
arr := decode_array(typ.$(field.name), data_fmt)!
|
||||
typ.$(field.name) = arr
|
||||
$if field.is_array {
|
||||
$if field.typ is $struct {
|
||||
mut data_fmt := data.replace(action_str, '')
|
||||
data_fmt = data.replace('define.${obj_name}', 'define')
|
||||
typ.$(field.name) = decode_array[field.elem_type](typ.$(field.name),
|
||||
data_fmt)!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,15 @@ module heroprompt
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
|
||||
@[heap]
|
||||
pub struct HeropromptDir {
|
||||
pub mut:
|
||||
name string
|
||||
path pathlib.Path
|
||||
files []&HeropromptFile @[skip; str: skip]
|
||||
dirs []&HeropromptDir
|
||||
}
|
||||
|
||||
// Parameters for adding a file to a directory
|
||||
@[params]
|
||||
pub struct AddFileParams {
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
module heroprompt
|
||||
|
||||
// import freeflowuniverse.herolib.data.paramsparser
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import os
|
||||
|
||||
pub struct HeropromptFile {
|
||||
pub mut:
|
||||
content string
|
||||
path pathlib.Path
|
||||
name string
|
||||
}
|
||||
|
||||
// Utility function to get file extension with special handling for common files
|
||||
pub fn get_file_extension(filename string) string {
|
||||
// Handle special cases for common files without extensions
|
||||
@@ -57,3 +68,9 @@ pub fn get_file_extension(filename string) string {
|
||||
|
||||
return parts[parts.len - 1]
|
||||
}
|
||||
|
||||
// Read the file content
|
||||
pub fn (fl HeropromptFile) read() !string {
|
||||
content := os.read_file(fl.path.path)!
|
||||
return content
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
module heroprompt
|
||||
|
||||
import rand
|
||||
|
||||
// HeropromptSession manages multiple workspaces for organizing AI prompts
|
||||
pub struct HeropromptSession {
|
||||
pub mut:
|
||||
id string // Unique session identifier
|
||||
workspaces []&HeropromptWorkspace // List of workspaces in this session
|
||||
}
|
||||
|
||||
// new_session creates a new heroprompt session with a unique ID
|
||||
pub fn new_session() HeropromptSession {
|
||||
return HeropromptSession{
|
||||
id: rand.uuid_v4()
|
||||
workspaces: []
|
||||
}
|
||||
}
|
||||
|
||||
// add_workspace creates and adds a new workspace to the session
|
||||
pub fn (mut self HeropromptSession) add_workspace(args_ NewWorkspaceParams) !&HeropromptWorkspace {
|
||||
mut wsp := &HeropromptWorkspace{}
|
||||
wsp = wsp.new(args_)!
|
||||
self.workspaces << wsp
|
||||
return wsp
|
||||
}
|
||||
@@ -5,19 +5,11 @@ import time
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
|
||||
// HeropromptWorkspace represents a workspace containing multiple directories
|
||||
// and their selected files for AI prompt generation
|
||||
@[heap]
|
||||
pub struct HeropromptWorkspace {
|
||||
pub mut:
|
||||
name string = 'default' // Workspace name
|
||||
dirs []&HeropromptDir // List of directories in this workspace
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct NewWorkspaceParams {
|
||||
pub mut:
|
||||
struct NewWorkspaceParams {
|
||||
mut:
|
||||
name string
|
||||
path string
|
||||
}
|
||||
|
||||
/// Create a new workspace
|
||||
@@ -28,10 +20,200 @@ fn (wsp HeropromptWorkspace) new(args_ NewWorkspaceParams) !&HeropromptWorkspace
|
||||
args.name = generate_random_workspace_name()
|
||||
}
|
||||
|
||||
workspace := get(name: args.name)!
|
||||
// Validate and set base path
|
||||
if args.path.len > 0 {
|
||||
if !os.exists(args.path) {
|
||||
return error('Workspace path does not exist: ${args.path}')
|
||||
}
|
||||
if !os.is_dir(args.path) {
|
||||
return error('Workspace path is not a directory: ${args.path}')
|
||||
}
|
||||
}
|
||||
|
||||
mut workspace := &HeropromptWorkspace{
|
||||
name: args.name
|
||||
base_path: os.real_path(args.path)
|
||||
}
|
||||
return workspace
|
||||
}
|
||||
|
||||
// WorkspaceItem represents a file or directory in the workspace tree
|
||||
pub struct WorkspaceItem {
|
||||
pub mut:
|
||||
name string // Item name (file or directory name)
|
||||
path string // Full path to the item
|
||||
is_directory bool // True if this is a directory
|
||||
is_file bool // True if this is a file
|
||||
size i64 // File size in bytes (0 for directories)
|
||||
extension string // File extension (empty for directories)
|
||||
children []WorkspaceItem // Child items (for directories)
|
||||
is_expanded bool // Whether directory is expanded in UI
|
||||
is_selected bool // Whether this item is selected for prompts
|
||||
depth int // Depth level in the tree (0 = root)
|
||||
}
|
||||
|
||||
// WorkspaceList represents the complete hierarchical listing of a workspace
|
||||
pub struct WorkspaceList {
|
||||
pub mut:
|
||||
root_path string // Root path of the workspace
|
||||
items []WorkspaceItem // Top-level items in the workspace
|
||||
total_files int // Total number of files
|
||||
total_dirs int // Total number of directories
|
||||
}
|
||||
|
||||
// list returns the complete hierarchical structure of the workspace
|
||||
pub fn (wsp HeropromptWorkspace) list() WorkspaceList {
|
||||
mut result := WorkspaceList{
|
||||
root_path: wsp.base_path
|
||||
}
|
||||
|
||||
if wsp.base_path.len == 0 || !os.exists(wsp.base_path) {
|
||||
return result
|
||||
}
|
||||
|
||||
// Build the complete tree structure (ALL files and directories)
|
||||
result.items = wsp.build_workspace_tree(wsp.base_path, 0)
|
||||
wsp.calculate_totals(result.items, mut result)
|
||||
|
||||
// Mark selected items
|
||||
wsp.mark_selected_items(mut result.items)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// build_workspace_tree recursively builds the workspace tree structure
|
||||
fn (wsp HeropromptWorkspace) build_workspace_tree(path string, depth int) []WorkspaceItem {
|
||||
mut items := []WorkspaceItem{}
|
||||
|
||||
entries := os.ls(path) or { return items }
|
||||
|
||||
for entry in entries {
|
||||
full_path := os.join_path(path, entry)
|
||||
|
||||
if os.is_dir(full_path) {
|
||||
mut dir_item := WorkspaceItem{
|
||||
name: entry
|
||||
path: full_path
|
||||
is_directory: true
|
||||
is_file: false
|
||||
size: 0
|
||||
extension: ''
|
||||
is_expanded: false
|
||||
is_selected: false
|
||||
depth: depth
|
||||
}
|
||||
|
||||
// Recursively get children
|
||||
dir_item.children = wsp.build_workspace_tree(full_path, depth + 1)
|
||||
items << dir_item
|
||||
} else if os.is_file(full_path) {
|
||||
file_info := os.stat(full_path) or { continue }
|
||||
extension := get_file_extension(entry)
|
||||
|
||||
file_item := WorkspaceItem{
|
||||
name: entry
|
||||
path: full_path
|
||||
is_directory: false
|
||||
is_file: true
|
||||
size: file_info.size
|
||||
extension: extension
|
||||
children: []
|
||||
is_expanded: false
|
||||
is_selected: false
|
||||
depth: depth
|
||||
}
|
||||
items << file_item
|
||||
}
|
||||
}
|
||||
|
||||
// Sort: directories first, then files, both alphabetically
|
||||
items.sort_with_compare(fn (a &WorkspaceItem, b &WorkspaceItem) int {
|
||||
if a.is_directory && !b.is_directory {
|
||||
return -1
|
||||
}
|
||||
if !a.is_directory && b.is_directory {
|
||||
return 1
|
||||
}
|
||||
if a.name < b.name {
|
||||
return -1
|
||||
}
|
||||
if a.name > b.name {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
// calculate_totals counts total files and directories in the workspace
|
||||
fn (wsp HeropromptWorkspace) calculate_totals(items []WorkspaceItem, mut result WorkspaceList) {
|
||||
for item in items {
|
||||
if item.is_directory {
|
||||
result.total_dirs++
|
||||
wsp.calculate_totals(item.children, mut result)
|
||||
} else {
|
||||
result.total_files++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark_selected_items marks which items are currently selected for prompts
|
||||
fn (wsp HeropromptWorkspace) mark_selected_items(mut items []WorkspaceItem) {
|
||||
for mut item in items {
|
||||
// Check if this item is selected by comparing paths
|
||||
item.is_selected = wsp.is_item_selected(item.path)
|
||||
|
||||
// Recursively mark children
|
||||
if item.is_directory && item.children.len > 0 {
|
||||
wsp.mark_selected_items(mut item.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// is_item_selected checks if a specific path is selected in the workspace
|
||||
fn (wsp HeropromptWorkspace) is_item_selected(path string) bool {
|
||||
for dir in wsp.dirs {
|
||||
// Check if this directory is selected
|
||||
if dir.path.path == path {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if any file in this directory is selected
|
||||
for file in dir.files {
|
||||
if file.path.path == path {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively check subdirectories
|
||||
if wsp.is_path_in_selected_dirs(path, dir.dirs) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// is_path_in_selected_dirs recursively checks subdirectories for selected items
|
||||
fn (wsp HeropromptWorkspace) is_path_in_selected_dirs(path string, dirs []&HeropromptDir) bool {
|
||||
for dir in dirs {
|
||||
if dir.path.path == path {
|
||||
return true
|
||||
}
|
||||
|
||||
for file in dir.files {
|
||||
if file.path.path == path {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if wsp.is_path_in_selected_dirs(path, dir.dirs) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct AddDirParams {
|
||||
pub mut:
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
module heroprompt
|
||||
|
||||
// TODO: Implement template-based prompt generation
|
||||
fn (mut ws HeropromptWorkspace) heroprompt() !string {
|
||||
// TODO: fill in template based on selection
|
||||
return ''
|
||||
}
|
||||
|
||||
// TODO: Implement tree visualization utilities
|
||||
pub fn get_tree() {}
|
||||
|
||||
// TODO: Implement prompt formatting utilities
|
||||
pub fn format_prompt() {}
|
||||
@@ -2,7 +2,6 @@ module heroprompt
|
||||
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.core.playbook { PlayBook }
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
__global (
|
||||
heroprompt_global map[string]&HeropromptWorkspace
|
||||
@@ -35,7 +34,7 @@ pub fn get(args_ ArgsGet) !&HeropromptWorkspace {
|
||||
if !exists(args)! {
|
||||
set(obj)!
|
||||
} else {
|
||||
heroscript := context.hero_config_get('heroprompt', args.name)!
|
||||
heroscript := context.hero_config_get('heropromptworkspace', args.name)!
|
||||
mut obj_ := heroscript_loads(heroscript)!
|
||||
set_in_mem(obj_)!
|
||||
}
|
||||
@@ -52,20 +51,20 @@ pub fn set(o HeropromptWorkspace) ! {
|
||||
set_in_mem(o)!
|
||||
mut context := base.context()!
|
||||
heroscript := heroscript_dumps(o)!
|
||||
context.hero_config_set('heroprompt', o.name, heroscript)!
|
||||
context.hero_config_set('heropromptworkspace', o.name, heroscript)!
|
||||
}
|
||||
|
||||
// does the config exists?
|
||||
pub fn exists(args_ ArgsGet) !bool {
|
||||
mut context := base.context()!
|
||||
mut args := args_get(args_)
|
||||
return context.hero_config_exists('heroprompt', args.name)
|
||||
return context.hero_config_exists('heropromptworkspace', args.name)
|
||||
}
|
||||
|
||||
pub fn delete(args_ ArgsGet) ! {
|
||||
mut args := args_get(args_)
|
||||
mut context := base.context()!
|
||||
context.hero_config_delete('heroprompt', args.name)!
|
||||
context.hero_config_delete('heropromptworkspace', args.name)!
|
||||
if args.name in heroprompt_global {
|
||||
// del heroprompt_global[args.name]
|
||||
}
|
||||
@@ -79,7 +78,7 @@ fn set_in_mem(o HeropromptWorkspace) ! {
|
||||
}
|
||||
|
||||
pub fn play(mut plbook PlayBook) ! {
|
||||
mut install_actions := plbook.find(filter: 'heroprompt.configure')!
|
||||
mut install_actions := plbook.find(filter: 'heropromptworkspace.configure')!
|
||||
if install_actions.len > 0 {
|
||||
for install_action in install_actions {
|
||||
heroscript := install_action.heroscript()
|
||||
|
||||
@@ -1,51 +1,43 @@
|
||||
module heroprompt
|
||||
|
||||
import freeflowuniverse.herolib.data.paramsparser
|
||||
// import freeflowuniverse.herolib.data.encoderhero // temporarily commented out
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import os
|
||||
import freeflowuniverse.herolib.data.encoderhero
|
||||
|
||||
pub const version = '0.0.0'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
|
||||
pub struct HeropromptFile {
|
||||
// HeropromptWorkspace represents a workspace containing multiple directories
|
||||
// and their selected files for AI prompt generation
|
||||
@[heap]
|
||||
pub struct HeropromptWorkspace {
|
||||
pub mut:
|
||||
content string
|
||||
path pathlib.Path
|
||||
name string
|
||||
name string = 'default' // Workspace name
|
||||
base_path string // Base path of the workspace
|
||||
dirs []&HeropromptDir // List of directories in this workspace
|
||||
}
|
||||
|
||||
pub struct HeropromptDir {
|
||||
@[params]
|
||||
pub struct AddWorkspaceParams {
|
||||
pub mut:
|
||||
name string
|
||||
path pathlib.Path
|
||||
files []&HeropromptFile
|
||||
dirs []&HeropromptDir
|
||||
name string
|
||||
path string
|
||||
}
|
||||
|
||||
// pub fn (wsp HeropromptWorkspace) to_tag() {
|
||||
// tag := HeropromptTags.file_map
|
||||
// // We need to pass it to the template
|
||||
// }
|
||||
// add_workspace creates and adds a new workspace
|
||||
pub fn new_workspace(args_ AddWorkspaceParams) !&HeropromptWorkspace {
|
||||
mut wsp := &HeropromptWorkspace{}
|
||||
wsp = wsp.new(name: args_.name, path: args_.path)!
|
||||
return wsp
|
||||
}
|
||||
|
||||
// // pub fn (dir HeropromptDir) to_tag() {
|
||||
// // tag := HeropromptTags.file_content
|
||||
// // // We need to pass it to the template
|
||||
// // }
|
||||
// get_workspace gets the saved workspace
|
||||
pub fn get_workspace(args_ AddWorkspaceParams) !&HeropromptWorkspace {
|
||||
if args_.name.len == 0 {
|
||||
return error('Workspace name is required')
|
||||
}
|
||||
|
||||
// pub fn (fil HeropromptFile) to_tag() {
|
||||
// tag := HeropromptTags.file_content
|
||||
// // We need to pass it to the template
|
||||
// }
|
||||
|
||||
// pub enum HeropromptTags {
|
||||
// file_map
|
||||
// file_content
|
||||
// user_instructions
|
||||
// }
|
||||
return get(name: args_.name)!
|
||||
}
|
||||
|
||||
// your checking & initialization code if needed
|
||||
fn obj_init(mycfg_ HeropromptWorkspace) !HeropromptWorkspace {
|
||||
@@ -55,16 +47,11 @@ fn obj_init(mycfg_ HeropromptWorkspace) !HeropromptWorkspace {
|
||||
|
||||
/////////////NORMALLY NO NEED TO TOUCH
|
||||
|
||||
// TODO: Check the compiler issue with the encde/decode
|
||||
pub fn heroscript_dumps(obj HeropromptWorkspace) !string {
|
||||
// return encoderhero.encode[HeropromptWorkspace](obj)! // temporarily commented out
|
||||
return 'name: "${obj.name}"'
|
||||
return encoderhero.encode[HeropromptWorkspace](obj)!
|
||||
}
|
||||
|
||||
pub fn heroscript_loads(heroscript string) !HeropromptWorkspace {
|
||||
// mut obj := encoderhero.decode[HeropromptWorkspace](heroscript)! // temporarily commented out
|
||||
obj := HeropromptWorkspace{
|
||||
name: 'default'
|
||||
}
|
||||
mut obj := encoderhero.decode[HeropromptWorkspace](heroscript)!
|
||||
return obj
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
!!heroprompt.configure name:"default"
|
||||
!!heropromptworkspace.configure name:"default"
|
||||
|
||||
!!heroprompt.workspace_dir name:"default"
|
||||
path:"@HOME/code/github/freeflowuniverse/herolib/lib/builder"
|
||||
selection:"path1,path2" //paths are relative in the path of workspace
|
||||
filter_exclude:","
|
||||
filter_include:","
|
||||
// !!heropromptworkspace.workspace_dir name:"default"
|
||||
// path:"@HOME/code/github/freeflowuniverse/herolib/lib/builder"
|
||||
// selection:"path1,path2" //paths are relative in the path of workspace
|
||||
// filter_exclude:","
|
||||
// filter_include:","
|
||||
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
<file_map>
|
||||
/Users/mahmoud/code/github/freeflowuniverse/herolib
|
||||
└── docker
|
||||
└── docker_ubuntu_install.sh *
|
||||
├── herolib
|
||||
│ ├── .gitignore*
|
||||
│ ├── build.sh *
|
||||
│ └── debug.sh*
|
||||
</file_map>
|
||||
|
||||
<file_contents>
|
||||
File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh
|
||||
|
||||
```sh
|
||||
#!/bin/bash
|
||||
|
||||
# Exit immediately if a command exits with a non-zero status
|
||||
set -e
|
||||
|
||||
# Function to display an error message and exit
|
||||
error_exit() {
|
||||
echo "Error: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Update package index and upgrade system
|
||||
echo "Updating system packages..."
|
||||
sudo apt update && sudo apt upgrade -y || error_exit "Failed to update system packages."
|
||||
|
||||
# Install required packages for repository setup
|
||||
echo "Installing prerequisites..."
|
||||
sudo apt install -y ca-certificates curl gnupg || error_exit "Failed to install prerequisites."
|
||||
|
||||
# Create directory for Docker GPG key
|
||||
echo "Setting up GPG keyring..."
|
||||
sudo mkdir -p /etc/apt/keyrings || error_exit "Failed to create keyring directory."
|
||||
|
||||
# Add Docker's official GPG key
|
||||
DOCKER_GPG_KEY=/etc/apt/keyrings/docker.gpg
|
||||
echo "Adding Docker GPG key..."
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o $DOCKER_GPG_KEY || error_exit "Failed to add Docker GPG key."
|
||||
sudo chmod a+r $DOCKER_GPG_KEY
|
||||
|
||||
# Set up Docker repository
|
||||
echo "Adding Docker repository..."
|
||||
REPO_ENTRY="deb [arch=$(dpkg --print-architecture) signed-by=$DOCKER_GPG_KEY] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
if ! grep -Fxq "$REPO_ENTRY" /etc/apt/sources.list.d/docker.list; then
|
||||
echo "$REPO_ENTRY" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null || error_exit "Failed to add Docker repository."
|
||||
fi
|
||||
|
||||
# Update package index
|
||||
echo "Updating package index..."
|
||||
sudo apt update || error_exit "Failed to update package index."
|
||||
|
||||
# Install Docker Engine, CLI, and dependencies
|
||||
echo "Installing Docker Engine and dependencies..."
|
||||
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin || error_exit "Failed to install Docker packages."
|
||||
|
||||
# Verify Docker installation
|
||||
echo "Verifying Docker installation..."
|
||||
if ! docker --version; then
|
||||
error_exit "Docker installation verification failed."
|
||||
fi
|
||||
|
||||
# Run a test container
|
||||
echo "Running Docker test container..."
|
||||
if ! sudo docker run --rm hello-world; then
|
||||
error_exit "Docker test container failed to run."
|
||||
fi
|
||||
|
||||
# Add current user to Docker group (if not already added)
|
||||
echo "Configuring Docker group..."
|
||||
if ! groups $USER | grep -q '\bdocker\b'; then
|
||||
sudo usermod -aG docker $USER || error_exit "Failed to add user to Docker group."
|
||||
echo "User added to Docker group. Please log out and back in for this change to take effect."
|
||||
else
|
||||
echo "User is already in the Docker group."
|
||||
fi
|
||||
|
||||
# Enable Docker service on boot
|
||||
echo "Enabling Docker service on boot..."
|
||||
sudo systemctl enable docker || error_exit "Failed to enable Docker service."
|
||||
|
||||
# Success message
|
||||
echo "Docker installation completed successfully!"
|
||||
|
||||
```
|
||||
|
||||
File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/build.sh
|
||||
|
||||
```sh
|
||||
#!/bin/bash -e
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Copy installation files
|
||||
cp ../../install_v.sh ./scripts/install_v.sh
|
||||
cp ../../install_herolib.vsh ./scripts/install_herolib.vsh
|
||||
|
||||
# Docker image and container names
|
||||
DOCKER_IMAGE_NAME="herolib"
|
||||
DEBUG_CONTAINER_NAME="herolib"
|
||||
|
||||
function cleanup {
|
||||
if docker ps -aq -f name="$DEBUG_CONTAINER_NAME" &>/dev/null; then
|
||||
echo "Cleaning up leftover debug container..."
|
||||
docker rm -f "$DEBUG_CONTAINER_NAME" &>/dev/null || true
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Attempt to build the Docker image
|
||||
BUILD_LOG=$(mktemp)
|
||||
set +e
|
||||
docker build --name herolib --progress=plain -t "$DOCKER_IMAGE_NAME" .
|
||||
BUILD_EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
# Handle build failure
|
||||
if [ $BUILD_EXIT_CODE -ne 0 ]; then
|
||||
echo -e "\\n[ERROR] Docker build failed.\n"
|
||||
echo -e "remove the part which didn't build in the Dockerfile, the run again and to debug do:"
|
||||
echo docker run --name herolib -it --entrypoint=/bin/bash "herolib"
|
||||
exit $BUILD_EXIT_CODE
|
||||
else
|
||||
echo -e "\\n[INFO] Docker build completed successfully."
|
||||
fi
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/.gitignore
|
||||
|
||||
```
|
||||
.bash_history
|
||||
.openvscode-server/
|
||||
.cache/
|
||||
```
|
||||
|
||||
File: /Users/mahmoud/code/github/freeflowuniverse/herolib/docker/herolib/debug.sh
|
||||
|
||||
```sh
|
||||
#!/bin/bash -ex
|
||||
|
||||
# Get the directory where the script is located
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Remove any existing container named 'debug' (ignore errors)
|
||||
docker rm -f herolib > /dev/null 2>&1
|
||||
|
||||
docker run --name herolib -it \
|
||||
--entrypoint="/usr/local/bin/ourinit.sh" \
|
||||
-v "${SCRIPT_DIR}/scripts:/scripts" \
|
||||
-v "$HOME/code:/root/code" \
|
||||
-p 4100:8100 \
|
||||
-p 4101:8101 \
|
||||
-p 4102:8102 \
|
||||
-p 4379:6379 \
|
||||
-p 4022:22 \
|
||||
-p 4000:3000 herolib
|
||||
|
||||
```
|
||||
|
||||
</file_contents>
|
||||
<user_instructions>
|
||||
This is a small repo prompt example
|
||||
</user_instructions>
|
||||
Reference in New Issue
Block a user