git modules

This commit is contained in:
xtremxpert 2024-04-29 20:04:14 -04:00
parent c0a451f7e0
commit 5bdf5cd5ee
21 changed files with 616 additions and 0 deletions

View file

@ -0,0 +1,2 @@
from . import models
from . import wizard

View file

@ -0,0 +1,63 @@
#
# Bemade Inc.
#
# Copyright (C) July 2023 Bemade Inc. (<https://www.bemade.org>).
# Author: Marc Durepos (Contact : marc@bemade.org)
#
# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
# or modified copies of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
{
'name': 'Bemade Addons from Git Repositories',
'version': '17.0.1.0.0',
'summary': 'A way to install addons from git repositories.',
'description': """
This module allows you to install addons from git repositories.
Configuration:
Set the directory where the repository will be cloned and the directory where the activated addons are located.
Usage:
You can add a git repository in the Apps application and then enabled the addons from it.
In the Apps application, you will see a new option to add git repositories.
This will allow you to select the repository and the branch you want to install.
You can then navigate to apps and in the menu, you will see a new option to enabled addons from git repositories.
""",
'category': 'Generic Modules/Others',
'author': 'Bemade Inc.',
'website': 'https://www.bemade.org',
'license': 'OPL-1',
'depends': [
'base_import_module'
],
'data': [
# 'data/default_directories_data.xml',
'security/ir.model.access.csv',
'views/git_repos_views.xml',
'views/res_settings_views.xml',
'views/action_and_menu.xml',
'wizard/directory_wizard_views.xml',
'wizard/git_repos_wizard_views.xml',
], 'demo': [],
'assets': {
'web.assets_backend': [
'/bemade_git_repos_addons/static/src/views/*/*',
],
},
'installable': True,
'auto_install': False,
}

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data noupdate="0">
<!-- Server Action to set the default values -->
<record id="action_set_default_directories" model="ir.actions.server">
<field name="name">Set Default Directories</field>
<field name="model_id" ref="base.model_ir_config_parameter"/>
<field name="state">code</field>
<field name="code">
env['ir.config_parameter'].sudo().set_param('bemade_git_repos_addons.clone_dir', '.repos')
env['ir.config_parameter'].sudo().set_param('bemade_git_repos_addons.addons_dir', 'addons')
</field>
</record>
<!-- Automated Action -->
<record id="action_on_module_installation" model="base.automation">
<field name="name">On Module Installation</field>
<field name="model_id" ref="base.model_ir_module_module"/>
<field name="trigger">on_create</field>
<field name="filter_domain">[('name', '=', 'bemade_git_repos_addons'), ('state', '=', 'installed')]</field>
<field name="action_server_id" ref="action_set_default_directories"/>
</record>
</data>
</odoo>

View file

@ -0,0 +1,4 @@
from . import git_repos
from . import git_branch
from . import git_addons
from . import res_settings

View file

@ -0,0 +1,28 @@
from odoo import api, fields, models
import os
class GitAddons(models.Model):
_name = 'git.addons'
_description = 'Git Addons'
name = fields.Char(string='Addon Name')
branch_id = fields.Many2one('git.branch', string='Branch')
@api.model
def get_addons(self):
self.search([]).unlink() # Remove old records
branches = self.env['git.branch'].search([])
for branch in branches:
repos = branch.repos
addons_path = repos.addons_path
if os.path.isdir(addons_path):
addons = next(os.walk(addons_path))[1]
for addon in addons:
self.create({
'name': addon,
'branch_id': branch.id,
})
def action_update_addons(self):
self.get_addons()

View file

@ -0,0 +1,18 @@
from odoo import models, fields
class GitBranch(models.Model):
_name = 'git.branch'
_description = 'Git Branch'
name = fields.Char(string='Branch Name', required=True)
repo_id = fields.Many2one('git.repos', string='Repository')
active = fields.Boolean(string='Active', default=False)
branch_addons = fields.One2many(
comodel_name='git.addons',
inverse_name='branch_id',
string='Addons',
readonly=True)
# If there are additional fields or relations you need, please define them here

View file

@ -0,0 +1,84 @@
from odoo import models, fields, api, exceptions
class GitRepos(models.Model):
_name = 'git.repos'
_description = 'Git Repositories'
name = fields.Char(string='Name', required=True)
url = fields.Char(string='URL')
branches = fields.One2many('git.branch', 'repo_id', string='Branches', readonly=True)
active_branch = fields.Many2one('git.branch', string='Active Branch')
@api.onchange('url')
def _check_repo(self):
self.branches = [(5, 0, 0)] # clear existing branches
try:
branches_list = self.get_branches(self.url) # a function you need to implement to get branches from git
for branch in branches_list:
self.env['git.branch'].create({
'name': branch,
'repo_id': self.id
})
except:
return {
'warning': {
'title': "URL validation",
'message': "The URL is not valid or the repository is not accessible.",
},
}
@api.model
def get_branches(self, url):
try:
repo = Repo.clone_from(url, '/tmp/repo') # clone repository to a temp folder
branches = [str(branch) for branch in repo.branches]
return branches
except Exception as e:
# Log the error and return an empty list or handle the exception
return []
@api.model
def action_create_repo(self, vals_list=None):
"""
This method will be called from button that we have created using owl js
"""
if not vals_list:
vals_list = [{'name': 'Test Repo', 'url': 'http://example.com', 'active_branch': 'master'}]
repo = self.create(vals_list)
return repo
@api.model
def action_clone_repos(self):
try:
# Choose active branch
repo = Repo('/tmp/repos/' + self.name)
repo.git.checkout(self.active_branch.name)
except Exception as e:
# Log the error and handle the exception appropriately
pass
@api.model
def action_switch_branch(self, branch_id):
try:
# Choose a branch
repo = Repo('/tmp/repos/' + self.name)
repo.git.checkout(branch_id)
# Update active_branch field
self.active_branch = self.env['git.branch'].browse(branch_id)
except Exception as e:
# Log the error and handle the exception appropriately
pass
@api.model
def action_update_repos(self):
self._check_repo()
@api.model
def action_delete_repos(self):
# Delete the physical directory '/tmp/repos/'+self.name
# There is a lot of ways to do this. Here is one:
import shutil
shutil.rmtree('/tmp/repos/' + self.name)
# Delete the DB record
self.unlink()

View file

@ -0,0 +1,23 @@
from odoo import models, fields, api
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
_description = 'Directory Settings'
clone_dir = fields.Char(string='Clone Directory')
addons_dir = fields.Char(string='Addons Directory')
@api.model
def default_get(self, fields):
res = super().default_get(fields)
addons_dir = self.env['ir.config_parameter'].get_param('bemade_git_repos_addons.addons_dir')
clone_dir = self.env['ir.config_parameter'].get_param('bemade_git_repos_addons.clone_dir')
if 'addons_dir' in fields and addons_dir:
res['addons_dir'] = addons_dir
if 'clone_dir' in fields and clone_dir:
res['clone_dir'] = clone_dir
return res

View file

@ -0,0 +1,11 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
bemade_git_repos_addons.access_git_repos,bemade_git_repos.access_git_repos_user,bemade_git_repos_addons.model_git_repos,base.group_user,1,0,0,0
bemade_git_repos_addons.access_git_repos_admin,bemade_git_repos.access_git_repos_admin,bemade_git_repos_addons.model_git_repos,base.group_system,1,1,1,1
bemade_git_repos_addons.access_git_branch,bemade_git_repos.access_git_branch_user,bemade_git_repos_addons.model_git_branch,base.group_user,1,0,0,0
bemade_git_repos_addons.access_git_branch_admin,bemade_git_repos.access_git_branch_admin,bemade_git_repos_addons.model_git_branch,base.group_system,1,1,1,1
bemade_git_repos_addons.access_git_addons,bemade_git_repos.access_git_addons_user,bemade_git_repos_addons.model_git_addons,base.group_user,1,0,0,0
bemade_git_repos_addons.access_git_addons_admin,bemade_git_repos.access_git_addons_admin,bemade_git_repos_addons.model_git_addons,base.group_system,1,1,1,1
bemade_git_repos_addons.access_directory_wizard,bemade_git_repos.access_directory_wizard_user,bemade_git_repos_addons.model_directory_wizard,base.group_user,1,0,0,0
bemade_git_repos_addons.access_directory_wizard_admin,bemade_git_repos.access_directory_wizard_admin,bemade_git_repos_addons.model_directory_wizard,base.group_system,1,1,1,1
bemade_git_repos_addons.access_git_repos_wizard,bemade_git_repos.access_git_repos_wizard_user,bemade_git_repos_addons.model_git_repos_wizard,base.group_user,1,0,0,0
bemade_git_repos_addons.access_git_repos_wizard_admin,bemade_git_repos.access_git_repos_wizard_admin,bemade_git_repos_addons.model_git_repos_wizard,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 bemade_git_repos_addons.access_git_repos bemade_git_repos.access_git_repos_user bemade_git_repos_addons.model_git_repos base.group_user 1 0 0 0
3 bemade_git_repos_addons.access_git_repos_admin bemade_git_repos.access_git_repos_admin bemade_git_repos_addons.model_git_repos base.group_system 1 1 1 1
4 bemade_git_repos_addons.access_git_branch bemade_git_repos.access_git_branch_user bemade_git_repos_addons.model_git_branch base.group_user 1 0 0 0
5 bemade_git_repos_addons.access_git_branch_admin bemade_git_repos.access_git_branch_admin bemade_git_repos_addons.model_git_branch base.group_system 1 1 1 1
6 bemade_git_repos_addons.access_git_addons bemade_git_repos.access_git_addons_user bemade_git_repos_addons.model_git_addons base.group_user 1 0 0 0
7 bemade_git_repos_addons.access_git_addons_admin bemade_git_repos.access_git_addons_admin bemade_git_repos_addons.model_git_addons base.group_system 1 1 1 1
8 bemade_git_repos_addons.access_directory_wizard bemade_git_repos.access_directory_wizard_user bemade_git_repos_addons.model_directory_wizard base.group_user 1 0 0 0
9 bemade_git_repos_addons.access_directory_wizard_admin bemade_git_repos.access_directory_wizard_admin bemade_git_repos_addons.model_directory_wizard base.group_system 1 1 1 1
10 bemade_git_repos_addons.access_git_repos_wizard bemade_git_repos.access_git_repos_wizard_user bemade_git_repos_addons.model_git_repos_wizard base.group_user 1 0 0 0
11 bemade_git_repos_addons.access_git_repos_wizard_admin bemade_git_repos.access_git_repos_wizard_admin bemade_git_repos_addons.model_git_repos_wizard base.group_system 1 1 1 1

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<templates id="template" xml:space="preserve">
<t t-name="bemade_git_repos_addons.ButtonCreateReposView.Buttons" t-inherit="web.ListView.Buttons" t-inherit-mode="primary" owl="1">
<xpath expr="//div[@t-if='props.showButtons']" position="after">
<button type="button" t-on-click="onCreateRepos" class="btn btn-primary">
Create
</button>
</xpath>
</t>
</templates>

View file

@ -0,0 +1,21 @@
/** @odoo-module */
import { useService } from "@web/core/utils/hooks";
import { ListController } from "@web/views/list/list_controller";
export class ButtonCreateReposController extends ListController {
setup() {
super.setup();
this.orm = useService("orm");
}
async onCreateRepos() {
this.actionService.doAction({
type: 'ir.actions.act_window',
res_model: 'git.repos.wizard', // Replace 'your.wizard.model' with the model of your wizard
views: [[false, 'form']],
target: 'new',
});
}
}

View file

@ -0,0 +1,13 @@
/** @odoo-module */
import { listView } from "@web/views/list/list_view";
import { registry } from "@web/core/registry";
import { ButtonCreateReposController as Controller } from './button_create_repos_controller';
export const ButtonCreateReposView = {
...listView,
Controller,
buttonTemplate: 'bemade_git_repos_addons.ButtonCreateReposView.Buttons',
};
registry.category("views").add("button_create_repos", ButtonCreateReposView);

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data> <!-- Action to open the git_repos Tree View -->
<record id="action_git_repos" model="ir.actions.act_window">
<field name="name">Git Repositories</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">git.repos</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
</record>
<record id="action_git_addons" model="ir.actions.act_window">
<field name="name">Git Addons</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">git.addons</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
</record>
<!-- Menu item to open the 'Git Addons' -->
<menuitem id="menu_git_addons_main" name="Git Addons" parent="base.menu_apps" sequence="10" />
<!-- Sub-menu items -->
<menuitem id="menu_git_repos" name="Git Repositories" parent="menu_git_addons_main" action="action_git_repos" sequence="1"/>
<menuitem id="menu_git_addons" name="Git Addons" parent="menu_git_addons_main" action="action_git_addons" sequence="2"/>
<!-- Menu item to open the git_repos Tree View -->
<!-- <menuitem id="menu_git_repos" name="Git Repositories" parent="base.menu_settings" action="action_git_repos" sequence="1"/>-->
</data>
</odoo>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<!-- Tree View for the git_addons model -->
<record id="view_git_addons_tree" model="ir.ui.view">
<field name="name">git.addons.tree</field>
<field name="model">git.addons</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="branch_id"/>
<field name="active_branch"/>
</tree>
</field>
</record>
<!-- Form View for the git_addons model -->
<record id="view_git_addons_form" model="ir.ui.view">
<field name="name">git.addons.form</field>
<field name="model">git.addons</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
<field name="branch_id"/>
<field name="active_branch"/>
</group>
</sheet>
</form>
</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<!-- Tree View for the git_repos model -->
<record id="view_git_repos_tree" model="ir.ui.view">
<field name="name">git.repos.tree</field>
<field name="model">git.repos</field>
<field name="arch" type="xml">
<tree create="false" js_class="button_create_repos">
<field name="name"/>
<field name="url"/>
<field name="active_branch"/>
</tree>
</field>
</record>
<!-- Form View for the git_repos model -->
<record id="view_git_repos_form" model="ir.ui.view">
<field name="name">git.repos.form</field>
<field name="model">git.repos</field>
<field name="arch" type="xml">
<form create="false">
<sheet>
<group>
<field name="name"/>
<field name="url"/>
<field name="active_branch"/>
</group>
</sheet>
</form>
</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="directory_wizard_action" model="ir.actions.act_window">
<field name="name">Choose Directories</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">directory.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="view_res_config_settings" model="ir.ui.view">
<field name="name">res.config.settings.view.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="priority" eval="9999"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='about']" position="before">
<block title="Git Addons" groups="base.group_no_one" name="git_addons">
<setting id="git_directories" help="Settings for using git modules">
<div string="Directories" data-string="Directories">
<div class="row mt16">
<label string="Clone Directory" for="clone_dir"/>
<field name="clone_dir" readonly="1"/>
</div>
<div class="row mt16">
<label string="Addons Directory" for="addons_dir"/>
<field name="addons_dir" readonly="1"/>
</div>
<button name="%(directory_wizard_action)d" string="Choose Directories" type="action" class="oe_inline oe_stat_button"/>
</div>
</setting>
</block>
</xpath>
</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,2 @@
from . import directory_wizard
from . import git_repos_wizard

View file

@ -0,0 +1,76 @@
from odoo import models, fields, api
import os
class DirectoryWizard(models.TransientModel):
_name = 'directory.wizard'
_description = 'Directory Wizard'
# Directories to exclude from the list, including hidden directories and directories that are not relevant
EXCLUDED_DIRS = [
'.idea',
'.git',
'.odoo-deploy',
'.testing',
'conf',
'design-themes',
'enterprise',
'Notes',
'odoo',
'tools',
'venv',
]
def _get_directory_list(self):
# Fetch all directories in the current working directory
directories = [(d, d) for d in os.listdir(os.getcwd())
if os.path.isdir(d) and d not in self.EXCLUDED_DIRS]
return directories
addons_dir = fields.Selection(_get_directory_list, string='Addons Directory')
repos_dir = fields.Selection(_get_directory_list, string='Repos Directory')
new_directory = fields.Char(string='New Directory')
def create_directory(self):
for record in self:
if not os.path.exists(record.new_directory):
os.makedirs(record.new_directory)
wizard = self.create({'new_directory': False}) # reset the value of new_directory
return {
'name': 'Directory Wizard',
'res_model': self._name,
'res_id': wizard.id,
'views': [(False, 'form')],
'type': 'ir.actions.act_window',
'target': 'new',
}
else:
return {
'warning': {
'title': "Directory Exists",
'message': "The directory already exists, please choose another name or directory.",
}
}
def apply_selections(self):
IrConfigParameter = self.env['ir.config_parameter']
if self.addons_dir:
IrConfigParameter.set_param('bemade_git_repos_addons.addons_dir', self.addons_dir)
if self.repos_dir:
IrConfigParameter.set_param('bemade_git_repos_addons.clone_dir', self.repos_dir)
return {}
@api.model
def default_get(self, fields):
res = super().default_get(fields)
addons_dir = self.env['ir.config_parameter'].get_param('bemade_git_repos_addons.addons_dir')
repos_dir = self.env['ir.config_parameter'].get_param('bemade_git_repos_addons.clone_dir')
if 'addons_dir' in fields and addons_dir:
res['addons_dir'] = addons_dir
if 'repos_dir' in fields and repos_dir:
res['repos_dir'] = repos_dir
return res

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="directory_wizard_form_view" model="ir.ui.view">
<field name="name">directory.wizard.form</field>
<field name="model">directory.wizard</field>
<field name="arch" type="xml">
<form string="Directory Selection">
<sheet>
<notebook>
<page string="Set Directories">
<group>
<field name="addons_dir" string="Addons Directory"/>
<field name="repos_dir" string="Repos Directory"/>
</group>
</page>
<page string="Create New irectory">
<group>
<field name="new_directory" string="Directory Name"/>
<button name="create_directory" string="Create" type="object" class="btn-primary"/>
</group>
</page>
</notebook>
</sheet>
<footer>
<button name="apply_selections" string="Apply" type="object" class="btn-success"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>

View file

@ -0,0 +1,36 @@
from odoo import models, fields
class GitReposWizard(models.TransientModel):
_name = 'git.repos.wizard'
_description = 'Git Repos Wizard'
url = fields.Char(string='Repository URL', required=True, help='URL of the git repository you want to clone')
branch_id = fields.Many2one('git.branch', 'Active Branch')
def get_repo_branches(self):
self.ensure_one()
# code for pulling branch list from git repo using `self.url`
# here the git branch data should be transformed into {'name': 'branch_name'} form
branches_datum = [{'name': 'branch_name'}]
# logic for checking if repo can be reach and have branches
if not branches_datum:
raise exceptions.ValidationError('The Repository URL is not accurate or The repository has no branches.')
# create git.branch records or link with existing ones
for branch_data in branches_datum:
# def action_confirm(self):
# self.ensure_one()
#
# # Perform the git clone operation
# # Be careful, errors should be managed
# try:
# git.Repo.clone_from(self.url, self.clone_dir)
# except Exception as e:
# raise Warning(str(e))
#
# return {'type': 'ir.actions.act_window_close'}

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="view_git_repos_wizard_form" model="ir.ui.view">
<field name="name">git.repos.wizard.form</field>
<field name="model">git.repos.wizard</field>
<field name="arch" type="xml">
<form string="Clone Repository">
<group>
<field name="url"/>
<field name="branch_id"/>
</group>
<footer>
<!-- <button name="action_confirm" string="Clone" type="object" class="btn-primary"/>-->
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</data>
</odoo>