Class: Sxn::Core::ProjectManager

Inherits:
Object
  • Object
show all
Defined in:
lib/sxn/core/project_manager.rb

Overview

Manages project registration and configuration

Instance Method Summary collapse

Constructor Details

#initialize(config_manager = nil) ⇒ ProjectManager

Returns a new instance of ProjectManager.



8
9
10
# File 'lib/sxn/core/project_manager.rb', line 8

def initialize(config_manager = nil)
  @config_manager = config_manager || ConfigManager.new
end

Instance Method Details

#add_project(name, path, type: nil, default_branch: nil) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/sxn/core/project_manager.rb', line 12

def add_project(name, path, type: nil, default_branch: nil)
  validate_project_name!(name)
  validate_project_path!(path)

  # Detect project type if not provided
  type ||= Sxn::Rules::ProjectDetector.new(path).detect_project_type.to_s

  # Detect default branch if not provided
  default_branch ||= detect_default_branch(path)

  @config_manager.add_project(name, path, type: type, default_branch: default_branch)

  {
    name: name,
    path: File.expand_path(path),
    type: type,
    default_branch: default_branch
  }
end

#auto_register_projects(detected_projects) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/sxn/core/project_manager.rb', line 147

def auto_register_projects(detected_projects)
  results = []

  detected_projects.each do |project|
    result = add_project(
      project[:name],
      project[:path],
      type: project[:type]
    )
    results << { status: :success, project: result }
  rescue StandardError => e
    results << {
      status: :error,
      project: project,
      error: e.message
    }
  end

  results
end

#detect_project_type(path) ⇒ Object



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
# File 'lib/sxn/core/project_manager.rb', line 96

def detect_project_type(path)
  path = Pathname.new(path)

  # Rails detection
  return "rails" if (path / "Gemfile").exist? &&
                    (path / "config" / "application.rb").exist?

  # Ruby gem detection
  return "ruby" if (path / "Gemfile").exist? || Dir.glob((path / "*.gemspec").to_s).any?

  # Node.js/JavaScript detection
  if (path / "package.json").exist?
    begin
      package_json = JSON.parse((path / "package.json").read)
      return "nextjs" if package_json.dig("dependencies", "next")
      return "react" if package_json.dig("dependencies", "react")
      return "typescript" if (path / "tsconfig.json").exist?

      return "javascript"
    rescue StandardError
      return "javascript"
    end
  end

  "unknown"
end

#detect_projects(base_path = nil) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/sxn/core/project_manager.rb', line 74

def detect_projects(base_path = nil)
  base_path ||= Dir.pwd
  detected = []

  # Scan for common project types
  Dir.glob(File.join(base_path, "*")).each do |path|
    next unless File.directory?(path)
    next if File.basename(path).start_with?(".")

    project_type = detect_project_type(path)
    next if project_type == "unknown"

    detected << {
      name: File.basename(path),
      path: path,
      type: project_type
    }
  end

  detected
end

#get_project(name) ⇒ Object



58
59
60
61
62
63
# File 'lib/sxn/core/project_manager.rb', line 58

def get_project(name)
  project = @config_manager.get_project(name)
  raise Sxn::ProjectNotFoundError, "Project '#{name}' not found" unless project

  project
end

#get_project_rules(name) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/sxn/core/project_manager.rb', line 190

def get_project_rules(name)
  project = get_project(name)
  raise Sxn::ProjectNotFoundError, "Project '#{name}' not found" unless project

  # Get project-specific rules from config
  config = @config_manager.get_config
  project_config = config.projects[name]

  rules = project_config&.dig("rules") || {}

  # Add default rules based on project type
  default_rules = get_default_rules_for_type(project[:type])

  merge_rules(default_rules, rules)
end

#list_projectsObject



54
55
56
# File 'lib/sxn/core/project_manager.rb', line 54

def list_projects
  @config_manager.list_projects
end

#project_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
68
# File 'lib/sxn/core/project_manager.rb', line 65

def project_exists?(name)
  project = @config_manager.get_project(name)
  !project.nil?
end

#remove_project(name) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/sxn/core/project_manager.rb', line 32

def remove_project(name)
  project = @config_manager.get_project(name)
  raise Sxn::ProjectNotFoundError, "Project '#{name}' not found" unless project

  # Check if project is used in any active sessions
  session_manager = SessionManager.new(@config_manager)
  active_sessions = session_manager.list_sessions(status: "active")

  sessions_using_project = active_sessions.select do |session|
    session[:projects].include?(name)
  end

  unless sessions_using_project.empty?
    session_names = sessions_using_project.map { |s| s[:name] }.join(", ")
    raise Sxn::ProjectInUseError,
          "Project '#{name}' is used in active sessions: #{session_names}"
  end

  @config_manager.remove_project(name)
  true
end

#scan_projects(_base_path = nil) ⇒ Object



70
71
72
# File 'lib/sxn/core/project_manager.rb', line 70

def scan_projects(_base_path = nil)
  @config_manager.detect_projects
end

#update_project(name, updates = {}) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/sxn/core/project_manager.rb', line 123

def update_project(name, updates = {})
  project = get_project(name)
  raise Sxn::ProjectNotFoundError, "Project '#{name}' not found" unless project

  # Validate updates
  raise Sxn::InvalidProjectPathError, "Path is not a directory" if updates[:path] && !File.directory?(updates[:path])

  @config_manager.update_project(name, updates)
  @config_manager.get_project(name) || raise(Sxn::ProjectNotFoundError,
                                             "Project '#{name}' was deleted during update")
end

#validate_project(name) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/sxn/core/project_manager.rb', line 168

def validate_project(name)
  project = get_project(name)
  raise Sxn::ProjectNotFoundError, "Project '#{name}' not found" unless project

  issues = []

  # Check if path exists
  issues << "Project path does not exist: #{project[:path]}" unless File.directory?(project[:path])

  # Check if it's a git repository
  issues << "Project path is not a git repository" unless git_repository?(project[:path])

  # Check if path is readable
  issues << "Project path is not readable" unless File.readable?(project[:path])

  {
    valid: issues.empty?,
    issues: issues,
    project: project
  }
end

#validate_projectsObject



135
136
137
138
139
140
141
142
143
144
145
# File 'lib/sxn/core/project_manager.rb', line 135

def validate_projects
  projects = list_projects
  results = []

  projects.each do |project|
    result = validate_project(project[:name])
    results << result
  end

  results
end