Added git information
This commit is contained in:
45
app.rb
45
app.rb
@@ -13,6 +13,7 @@ require "puma"
|
|||||||
require_relative "classes/config"
|
require_relative "classes/config"
|
||||||
require_relative "classes/gitinfo"
|
require_relative "classes/gitinfo"
|
||||||
require_relative "classes/db"
|
require_relative "classes/db"
|
||||||
|
require_relative "classes/systeminfo"
|
||||||
|
|
||||||
def print_error_page(error_status, error_meaasge)
|
def print_error_page(error_status, error_meaasge)
|
||||||
@page_name = "Ошибка выполнения"
|
@page_name = "Ошибка выполнения"
|
||||||
@@ -38,12 +39,52 @@ use Rack::Session::Pool, :expire_after => 2592000
|
|||||||
|
|
||||||
get "/" do
|
get "/" do
|
||||||
@page_name = "Система сборки rpm пакетов"
|
@page_name = "Система сборки rpm пакетов"
|
||||||
erb :index
|
repo = GitRepo.new(cfg.get_repo, db)
|
||||||
|
if repo.path.nil?
|
||||||
|
print_error_page(503, "Путь к репозиториям не существует")
|
||||||
|
else
|
||||||
|
repo_data = repo.getrepos
|
||||||
|
@repos_number = repo_data.length
|
||||||
|
erb :index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/repos/:reponame/:branch" do
|
||||||
|
@page_name = params["reponame"]
|
||||||
|
repo = GitRepo.new(cfg.get_repo, db)
|
||||||
|
if repo.path.nil?
|
||||||
|
print_error_page(503, "Путь к репозиториям не существует")
|
||||||
|
else
|
||||||
|
tmp_result = repo.repo_info(params["reponame"], params["branch"])
|
||||||
|
if tmp_result[:error].nil?
|
||||||
|
@repo_data = tmp_result
|
||||||
|
@ip_addr = systeminfo_get_ip
|
||||||
|
@user_name = systeminfo_get_username
|
||||||
|
@path_to_repo = File.join(repo.path, params["reponame"] + ".git")
|
||||||
|
erb :gitinfo
|
||||||
|
else
|
||||||
|
print_error_page(503, tmp_result[:error])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/repos/:reponame" do
|
get "/repos/:reponame" do
|
||||||
@page_name = params["reponame"]
|
@page_name = params["reponame"]
|
||||||
erb :gits
|
repo = GitRepo.new(cfg.get_repo, db)
|
||||||
|
if repo.path.nil?
|
||||||
|
print_error_page(503, "Путь к репозиториям не существует")
|
||||||
|
else
|
||||||
|
tmp_result = repo.repo_info(params["reponame"])
|
||||||
|
if tmp_result[:error].nil?
|
||||||
|
@repo_data = tmp_result
|
||||||
|
@ip_addr = systeminfo_get_ip
|
||||||
|
@user_name = systeminfo_get_username
|
||||||
|
@path_to_repo = File.join(repo.path, params["reponame"] + ".git")
|
||||||
|
erb :gitinfo
|
||||||
|
else
|
||||||
|
print_error_page(503, tmp_result[:error])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/repos" do
|
get "/repos" do
|
||||||
|
|||||||
@@ -59,22 +59,83 @@ class GitRepo
|
|||||||
|
|
||||||
def getrepos
|
def getrepos
|
||||||
repos_data = []
|
repos_data = []
|
||||||
repos_files = Dir[File.join(@path, "*.git")]
|
File.open("locks/gitcreate", "r") do |f|
|
||||||
repos_files.each do |fl|
|
f.flock(File::LOCK_SH)
|
||||||
repo_name = File.basename(fl, ".git")
|
repos_files = Dir[File.join(@path, "*.git")]
|
||||||
db_info = @db.get_repo_info_by_name(repo_name)
|
repos_files.each do |fl|
|
||||||
unless db_info.nil?
|
repo_name = File.basename(fl, ".git")
|
||||||
db_info = db_info.first
|
db_info = @db.get_repo_info_by_name(repo_name)
|
||||||
repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public }
|
unless db_info.nil?
|
||||||
else
|
|
||||||
result = create_git_db_only(repo_name)
|
|
||||||
if result.nil?
|
|
||||||
db_info = @db.get_repo_info_by_name(repo_name)
|
|
||||||
db_info = db_info.first
|
db_info = db_info.first
|
||||||
repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public }
|
repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public }
|
||||||
|
else
|
||||||
|
result = create_git_db_only(repo_name)
|
||||||
|
if result.nil?
|
||||||
|
db_info = @db.get_repo_info_by_name(repo_name)
|
||||||
|
db_info = db_info.first
|
||||||
|
repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
repos_data
|
repos_data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def repo_info(reponame, branch = nil)
|
||||||
|
info = {}
|
||||||
|
result = ""
|
||||||
|
@error = nil
|
||||||
|
repos_data = { :full => 0 }
|
||||||
|
git_path = File.join(@path, reponame + ".git")
|
||||||
|
File.open("locks/gitcreate", "r") do |f|
|
||||||
|
f.flock(File::LOCK_SH)
|
||||||
|
if File.exist?(git_path)
|
||||||
|
repo = Rugged::Repository.new(git_path)
|
||||||
|
db_info = @db.get_repo_info_by_name(reponame)
|
||||||
|
unless db_info.nil?
|
||||||
|
db_info = db_info.first
|
||||||
|
repos_data = { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public, :full => 1 }
|
||||||
|
else
|
||||||
|
result = create_git_db_only(reponame)
|
||||||
|
if result.nil?
|
||||||
|
db_info = @db.get_repo_info_by_name(reponame)
|
||||||
|
db_info = db_info.first
|
||||||
|
repos_data = { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public, :full => 1 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if repos_data[:full] == 1
|
||||||
|
info[:info] = repos_data
|
||||||
|
if repo.empty?
|
||||||
|
info[:commits] = []
|
||||||
|
info[:branches] = []
|
||||||
|
info[:tags] = []
|
||||||
|
else
|
||||||
|
ref = repo.head
|
||||||
|
unless branch.nil?
|
||||||
|
ref_name = File.join("refs/heads/", branch)
|
||||||
|
ref = repo.references[ref_name]
|
||||||
|
end
|
||||||
|
commits = []
|
||||||
|
unless ref.nil?
|
||||||
|
walker = Rugged::Walker.new(repo)
|
||||||
|
walker.sorting(Rugged::SORT_DATE)
|
||||||
|
walker.push(ref.target)
|
||||||
|
commits = walker.map do |commit|
|
||||||
|
{ :message => commit.message, :author => commit.author, :time => commit.time, :sha => commit.oid }
|
||||||
|
end.first(10)
|
||||||
|
end
|
||||||
|
info[:commits] = commits
|
||||||
|
info[:branches] = repo.branches.each_name(:local).sort
|
||||||
|
info[:tags] = repo.tags.map { |tag| tag.name }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@error = result
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@error = "Репозиторий отсутсвует"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
info[:error] = @error
|
||||||
|
info
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
10
classes/systeminfo.rb
Normal file
10
classes/systeminfo.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
require "socket"
|
||||||
|
require "etc"
|
||||||
|
|
||||||
|
def systeminfo_get_ip
|
||||||
|
Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
|
||||||
|
end
|
||||||
|
|
||||||
|
def systeminfo_get_username
|
||||||
|
Etc.getpwuid(Process.uid).name
|
||||||
|
end
|
||||||
7
public/assets/bootstrap/js/bootstrap.bundle.min.js
vendored
Normal file
7
public/assets/bootstrap/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/js/jquery-3.7.1.min.js
vendored
Normal file
2
public/js/jquery-3.7.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
public/js/jquery-confirm.min.js
vendored
Normal file
10
public/js/jquery-confirm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -16,7 +16,7 @@
|
|||||||
<p class="text-muted mb-0">Copyright © 2025 BayRepo</p>
|
<p class="text-muted mb-0">Copyright © 2025 BayRepo</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
<script src="/assets/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
202
views/gitinfo.erb
Normal file
202
views/gitinfo.erb
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
<%= erb :header %>
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
|
<li class="nav-item" role="presentation"><a class="nav-link active" role="tab" data-bs-toggle="tab" href="#tab-1">Общая информация</a></li>
|
||||||
|
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-2">Список коммитов</a></li>
|
||||||
|
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-3">Список тэгов</a></li>
|
||||||
|
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-4">Клонировать</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active" role="tabpanel" id="tab-1">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-10">
|
||||||
|
<p style="font-weight: bold;"><%= @repo_data[:info][:reponame] %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-4" style="background: #d3e2ff;border-radius: 15px;padding-top: 20px;padding-bottom: 20px;">
|
||||||
|
<p>
|
||||||
|
<% if @repo_data[:info][:descr].nil? || @repo_data[:info][:descr] == "" %>
|
||||||
|
"Нет описания"
|
||||||
|
<% else %>
|
||||||
|
<%= @repo_data[:info][:descr] %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<p style="color: var(--bs-red);">Доступные ветки</p>
|
||||||
|
<ul>
|
||||||
|
<% @repo_data[:branches].each do |br| %>
|
||||||
|
<li><a href="/repos/<%= ERB::Util.url_encode(@page_name) %>/<%= ERB::Util.url_encode(br) %>"><%= br %></a></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane" role="tabpanel" id="tab-2">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-10">
|
||||||
|
<p style="font-weight: bold;"><%= @repo_data[:info][:reponame] %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-4" style="background: #d3e2ff;border-radius: 15px;padding-top: 20px;padding-bottom: 20px;">
|
||||||
|
<p>
|
||||||
|
<% if @repo_data[:info][:descr].nil? || @repo_data[:info][:descr] == "" %>
|
||||||
|
"Нет описания"
|
||||||
|
<% else %>
|
||||||
|
<%= @repo_data[:info][:descr] %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<p style="color: var(--bs-red);">Список 10 последних коммитов</p>
|
||||||
|
<div class="container">
|
||||||
|
<% @repo_data[:commits].each do |commit| %>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-12" style="background: #ffe76a;"><em><%= commit[:sha] %></em></div>
|
||||||
|
<div class="col col-8 offset-4">
|
||||||
|
<p><%= commit[:author][:name] %> (<%= commit[:time] %>): <%= commit[:message] %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane" role="tabpanel" id="tab-3">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-10">
|
||||||
|
<p style="font-weight: bold;"><%= @repo_data[:info][:reponame] %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-4" style="background: #d3e2ff;border-radius: 15px;padding-top: 20px;padding-bottom: 20px;">
|
||||||
|
<p>
|
||||||
|
<% if @repo_data[:info][:descr].nil? || @repo_data[:info][:descr] == "" %>
|
||||||
|
"Нет описания"
|
||||||
|
<% else %>
|
||||||
|
<%= @repo_data[:info][:descr] %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<p style="color: var(--bs-red);">Тэги проекта</p>
|
||||||
|
<ul>
|
||||||
|
<% @repo_data[:tags].each do |tags| %>
|
||||||
|
<li><%= tags %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane" role="tabpanel" id="tab-4">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-10">
|
||||||
|
<p style="font-weight: bold;"><%= @repo_data[:info][:reponame] %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row align-items-start">
|
||||||
|
<div class="col-4" style="background: #d3e2ff;border-radius: 15px;padding-top: 20px;padding-bottom: 20px;">
|
||||||
|
<p>
|
||||||
|
<% if @repo_data[:info][:descr].nil? || @repo_data[:info][:descr] == "" %>
|
||||||
|
"Нет описания"
|
||||||
|
<% else %>
|
||||||
|
<%= @repo_data[:info][:descr] %>
|
||||||
|
<% end %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<p style="color: var(--bs-red);">Клонировать репозиторий</p>
|
||||||
|
<ul>
|
||||||
|
<li>git clone <%= @user_name %>@<%= @ip_addr %>:<%= @path_to_repo %></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container" style="padding-top: 20px;">
|
||||||
|
<form method="post" action="/gitdelete">
|
||||||
|
<input class="form-control" type="hidden" id="reponame" name="reponame" value="repo">
|
||||||
|
<button class="btn btn-primary" type="submit" id="delete">Удалить</button>
|
||||||
|
</form>
|
||||||
|
<div id="winkeeper"></div>
|
||||||
|
</div>
|
||||||
|
<script src="/js/jquery-confirm.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$("#delete").confirm({
|
||||||
|
title: 'Подтвердите удаление репозитория!',
|
||||||
|
content: '' +
|
||||||
|
'<div class="container">' +
|
||||||
|
'<form action="/gitdelete" class="formName" method="post">' +
|
||||||
|
'<div class="text-danger mx-auto p-2">' +
|
||||||
|
'<label>Введите имя удаляемого репозитория</label>' +
|
||||||
|
'<input type="text" class="frmchk form-control" required name="reponamedup"/>' +
|
||||||
|
'</div>' +
|
||||||
|
'</form>' +
|
||||||
|
'</div>',
|
||||||
|
container: '#winkeeper',
|
||||||
|
theme: 'bootstrap',
|
||||||
|
buttons: {
|
||||||
|
formSubmit: {
|
||||||
|
text: 'Удалить',
|
||||||
|
titleClass: 'text-danger mx-auto p-2',
|
||||||
|
btnClass: 'btn btn-danger',
|
||||||
|
action: function () {
|
||||||
|
var correct_name = $("#reponame").val();
|
||||||
|
var name = this.$content.find('.frmchk').val();
|
||||||
|
if(!name){
|
||||||
|
$.alert({
|
||||||
|
title: 'Предупреждение!',
|
||||||
|
content: 'Имя не может быть пустым',
|
||||||
|
container: '#winkeeper',
|
||||||
|
theme: 'bootstrap',
|
||||||
|
buttons: {
|
||||||
|
ok: {
|
||||||
|
text: 'Хорошо',
|
||||||
|
btnClass: 'btn btn-danger',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (name != correct_name){
|
||||||
|
$.alert({
|
||||||
|
title: 'Предупреждение!',
|
||||||
|
content: 'Имя задано неверно',
|
||||||
|
container: '#winkeeper',
|
||||||
|
theme: 'bootstrap',
|
||||||
|
buttons: {
|
||||||
|
ok: {
|
||||||
|
text: 'Хорошо',
|
||||||
|
btnClass: 'btn btn-danger',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.$content.find('form').submit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
text: 'Отменить',
|
||||||
|
btnClass: 'btn btn-primary',
|
||||||
|
action: function () {
|
||||||
|
//close
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<%= erb :footer %>
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
<title><%= @page_name %></title>
|
<title><%= @page_name %></title>
|
||||||
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
|
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="/assets/css/Footer-Dark-icons.css">
|
<link rel="stylesheet" href="/assets/css/Footer-Dark-icons.css">
|
||||||
|
<script src="/js/jquery-3.7.1.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"></path>
|
<path d="M4 11H2v3h2v-3zm5-4H7v7h2V7zm5-5v12h-2V2h2zm-2-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1h-2zM6 7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7zm-5 4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-3z"></path>
|
||||||
</svg></div>
|
</svg></div>
|
||||||
<div class="px-3">
|
<div class="px-3">
|
||||||
<h2 class="fw-bold mb-0">100</h2>
|
<h2 class="fw-bold mb-0"><%= @repos_number %></h2>
|
||||||
<p class="mb-0">Репозиториев</p>
|
<p class="mb-0">Репозиториев</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user