latest pushes
This commit is contained in:
@@ -1,45 +1,73 @@
|
|||||||
|
// Copyright (C) 2024 Bellande Algorithm Model Research Innovation Center, Ronaldson Bellande
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
class BellandeFormat {
|
class BellandeFormat {
|
||||||
parseBellande(filePath) {
|
parseBellande(filePath) {
|
||||||
const content = fs.readFileSync(filePath, 'utf8');
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
const lines = content.split('\n');
|
const lines = content.split('\n');
|
||||||
return this.parseLines(lines);
|
const parsedData = this.parseLines(lines);
|
||||||
|
return this.toStringRepresentation(parsedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseLines(lines) {
|
parseLines(lines) {
|
||||||
const result = {};
|
const result = {};
|
||||||
const stack = [[-1, result]];
|
let currentKey = null;
|
||||||
|
let currentList = null;
|
||||||
|
const indentStack = [[-1, result]];
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const stripped = line.trim();
|
const stripped = line.trim();
|
||||||
if (!stripped || stripped.startsWith('#')) continue;
|
if (!stripped || stripped.startsWith('#')) continue;
|
||||||
|
|
||||||
const indent = line.length - line.trimLeft().length;
|
const indent = line.length - line.trimLeft().length;
|
||||||
while (stack.length && indent <= stack[stack.length - 1][0]) {
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
const parent = stack[stack.length - 1][1];
|
while (indentStack.length && indent <= indentStack[indentStack.length - 1][0]) {
|
||||||
|
const popped = indentStack.pop();
|
||||||
|
if (Array.isArray(popped[1])) {
|
||||||
|
currentList = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stripped.includes(':')) {
|
if (stripped.includes(':')) {
|
||||||
const [key, value] = stripped.split(':').map(s => s.trim());
|
const [key, value] = stripped.split(':').map(s => s.trim());
|
||||||
|
currentKey = key;
|
||||||
if (value) {
|
if (value) {
|
||||||
parent[key] = this.parseValue(value);
|
result[key] = this.parseValue(value);
|
||||||
} else {
|
} else {
|
||||||
const newDict = {};
|
result[key] = [];
|
||||||
parent[key] = newDict;
|
currentList = result[key];
|
||||||
stack.push([indent, newDict]);
|
indentStack.push([indent, currentList]);
|
||||||
}
|
}
|
||||||
} else if (stripped.startsWith('-')) {
|
} else if (stripped.startsWith('-')) {
|
||||||
const value = stripped.slice(1).trim();
|
const value = stripped.slice(1).trim();
|
||||||
if (Array.isArray(parent)) {
|
const parsedValue = this.parseValue(value);
|
||||||
parent.push(this.parseValue(value));
|
if (currentList !== null) {
|
||||||
|
currentList.push(parsedValue);
|
||||||
} else {
|
} else {
|
||||||
const newList = [this.parseValue(value)];
|
if (Object.keys(result).length === 0) {
|
||||||
const lastKey = Object.keys(parent).pop();
|
result = [parsedValue];
|
||||||
parent[lastKey] = newList;
|
currentList = result;
|
||||||
stack.push([indent, newList]);
|
indentStack = [[-1, result]];
|
||||||
|
} else {
|
||||||
|
result[currentKey] = [parsedValue];
|
||||||
|
currentList = result[currentKey];
|
||||||
|
indentStack.push([indent, currentList]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,9 +85,30 @@ class BellandeFormat {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toStringRepresentation(data) {
|
||||||
|
if (typeof data === 'object' && data !== null) {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
const items = data.map(item => this.toStringRepresentation(item));
|
||||||
|
return '[' + items.join(', ') + ']';
|
||||||
|
} else {
|
||||||
|
const items = Object.entries(data).map(([k, v]) => `"${k}": ${this.toStringRepresentation(v)}`);
|
||||||
|
return '{' + items.join(', ') + '}';
|
||||||
|
}
|
||||||
|
} else if (typeof data === 'string') {
|
||||||
|
return `"${data}"`;
|
||||||
|
} else if (typeof data === 'number') {
|
||||||
|
return data.toString();
|
||||||
|
} else if (data === null) {
|
||||||
|
return 'null';
|
||||||
|
} else if (typeof data === 'boolean') {
|
||||||
|
return data.toString().toLowerCase();
|
||||||
|
} else {
|
||||||
|
return String(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writeBellande(data, filePath) {
|
writeBellande(data, filePath) {
|
||||||
const content = this.toBellandeString(data);
|
fs.writeFileSync(filePath, this.toBellandeString(data));
|
||||||
fs.writeFileSync(filePath, content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toBellandeString(data, indent = 0) {
|
toBellandeString(data, indent = 0) {
|
||||||
@@ -84,14 +133,19 @@ class BellandeFormat {
|
|||||||
|
|
||||||
formatValue(value) {
|
formatValue(value) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
return value.includes(' ') || value.includes(':') ? `"${value}"` : value;
|
if (value.includes(' ') || value.includes(':') || ['true', 'false', 'null'].includes(value.toLowerCase())) {
|
||||||
|
return `"${value}"`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
if (typeof value === 'boolean') {
|
if (typeof value === 'boolean') {
|
||||||
return value.toString();
|
return value.toString().toLowerCase();
|
||||||
}
|
}
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
return 'null';
|
return 'null';
|
||||||
}
|
}
|
||||||
return value.toString();
|
return String(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = BellandeFormat;
|
||||||
|
1
Package/Python/.gitignore
vendored
1
Package/Python/.gitignore
vendored
@@ -2,3 +2,4 @@ publish.sh
|
|||||||
tests
|
tests
|
||||||
setup.py
|
setup.py
|
||||||
dist
|
dist
|
||||||
|
src/bellande_format.egg-info
|
||||||
|
BIN
Package/Python/dist/bellande_format-0.1.1.tar.gz
vendored
Normal file
BIN
Package/Python/dist/bellande_format-0.1.1.tar.gz
vendored
Normal file
Binary file not shown.
2
Package/Python/publish.sh
Executable file
2
Package/Python/publish.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
python setup.py sdist
|
||||||
|
twine upload dist/*
|
40
Package/Python/setup.py
Normal file
40
Package/Python/setup.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
with open("README.md", "r", encoding="utf-8") as fh:
|
||||||
|
long_description = fh.read()
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="bellande_format",
|
||||||
|
version="0.1.1",
|
||||||
|
description="Bellande Format is a file format type",
|
||||||
|
long_description=long_description,
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
author="RonaldsonBellande",
|
||||||
|
author_email="ronaldsonbellande@gmail.com",
|
||||||
|
packages=find_packages(where="src"),
|
||||||
|
package_dir={"": "src"},
|
||||||
|
include_package_data=True,
|
||||||
|
install_requires=[
|
||||||
|
"numpy",
|
||||||
|
],
|
||||||
|
classifiers=[
|
||||||
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
],
|
||||||
|
keywords=["package", "setuptools"],
|
||||||
|
python_requires=">=3.0",
|
||||||
|
extras_require={
|
||||||
|
"dev": ["pytest", "pytest-cov[all]", "mypy", "black"],
|
||||||
|
},
|
||||||
|
entry_points={
|
||||||
|
'console_scripts': [
|
||||||
|
'Bellande_Format = bellande_parser:Bellande_Format',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
project_urls={
|
||||||
|
"Home": "https://github.com/RonaldsonBellande/bellande_format",
|
||||||
|
"Homepage": "https://github.com/RonaldsonBellande/bellande_format",
|
||||||
|
"documentation": "https://github.com/RonaldsonBellande/bellande_format",
|
||||||
|
"repository": "https://github.com/RonaldsonBellande/bellande_format",
|
||||||
|
},
|
||||||
|
)
|
0
Package/Rust/README.md
Normal file
0
Package/Rust/README.md
Normal file
2
Package/Rust/publish.sh
Executable file
2
Package/Rust/publish.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
cargo package
|
||||||
|
cargo publish
|
13
Package/Rust/src/Cargo.toml
Normal file
13
Package/Rust/src/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "bellande_parser"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["Ronaldson Bellande ronaldsonbellande@gmail.com"]
|
||||||
|
description = "Bellande File Format"
|
||||||
|
license = "GNU"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "bellande_parser.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
std = { version = "1.65", features = ["collections", "fs", "path"] }
|
196
Package/Rust/src/bellande_parser.rs
Normal file
196
Package/Rust/src/bellande_parser.rs
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
// Copyright (C) 2024 Bellande Algorithm Model Research Innovation Center, Ronaldson Bellande
|
||||||
|
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum BellandeValue {
|
||||||
|
String(String),
|
||||||
|
Integer(i64),
|
||||||
|
Float(f64),
|
||||||
|
Boolean(bool),
|
||||||
|
Null,
|
||||||
|
List(Vec<BellandeValue>),
|
||||||
|
Map(HashMap<String, BellandeValue>),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BellandeFormat;
|
||||||
|
|
||||||
|
impl BellandeFormat {
|
||||||
|
pub fn parse_bellande<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
file_path: P,
|
||||||
|
) -> Result<BellandeValue, std::io::Error> {
|
||||||
|
let content = fs::read_to_string(file_path)?;
|
||||||
|
let lines: Vec<&str> = content.lines().collect();
|
||||||
|
let parsed_data = self.parse_lines(&lines);
|
||||||
|
Ok(parsed_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_lines(&self, lines: &[&str]) -> BellandeValue {
|
||||||
|
let mut result = HashMap::new();
|
||||||
|
let mut current_key = String::new();
|
||||||
|
let mut current_list: Option<Vec<BellandeValue>> = None;
|
||||||
|
let mut indent_stack = vec![(0, &mut result)];
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
let stripped = line.trim();
|
||||||
|
if stripped.is_empty() || stripped.starts_with('#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let indent = line.len() - line.trim_start().len();
|
||||||
|
|
||||||
|
while indent_stack.last().map_or(false, |&(i, _)| indent <= i) {
|
||||||
|
indent_stack.pop();
|
||||||
|
current_list = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(colon_pos) = stripped.find(':') {
|
||||||
|
let (key, value) = stripped.split_at(colon_pos);
|
||||||
|
let key = key.trim().to_string();
|
||||||
|
let value = value[1..].trim();
|
||||||
|
|
||||||
|
current_key = key.clone();
|
||||||
|
if !value.is_empty() {
|
||||||
|
let parsed_value = self.parse_value(value);
|
||||||
|
indent_stack.last_mut().unwrap().1.insert(key, parsed_value);
|
||||||
|
} else {
|
||||||
|
let new_list = Vec::new();
|
||||||
|
indent_stack
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.insert(key, BellandeValue::List(new_list));
|
||||||
|
if let BellandeValue::List(list) = indent_stack
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.get_mut(¤t_key)
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
current_list = Some(list);
|
||||||
|
indent_stack.push((indent, list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if stripped.starts_with('-') {
|
||||||
|
let value = stripped[1..].trim();
|
||||||
|
let parsed_value = self.parse_value(value);
|
||||||
|
if let Some(list) = &mut current_list {
|
||||||
|
list.push(parsed_value);
|
||||||
|
} else {
|
||||||
|
let mut new_list = Vec::new();
|
||||||
|
new_list.push(parsed_value);
|
||||||
|
indent_stack
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.insert(current_key.clone(), BellandeValue::List(new_list));
|
||||||
|
if let BellandeValue::List(list) = indent_stack
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
.get_mut(¤t_key)
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
current_list = Some(list);
|
||||||
|
indent_stack.push((indent, list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BellandeValue::Map(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_value(&self, value: &str) -> BellandeValue {
|
||||||
|
if value.eq_ignore_ascii_case("true") {
|
||||||
|
BellandeValue::Boolean(true)
|
||||||
|
} else if value.eq_ignore_ascii_case("false") {
|
||||||
|
BellandeValue::Boolean(false)
|
||||||
|
} else if value.eq_ignore_ascii_case("null") {
|
||||||
|
BellandeValue::Null
|
||||||
|
} else if value.starts_with('"') && value.ends_with('"') {
|
||||||
|
BellandeValue::String(value[1..value.len() - 1].to_string())
|
||||||
|
} else if let Ok(int_value) = value.parse::<i64>() {
|
||||||
|
BellandeValue::Integer(int_value)
|
||||||
|
} else if let Ok(float_value) = value.parse::<f64>() {
|
||||||
|
BellandeValue::Float(float_value)
|
||||||
|
} else {
|
||||||
|
BellandeValue::String(value.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_bellande<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
data: &BellandeValue,
|
||||||
|
file_path: P,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
let content = self.to_bellande_string(data, 0);
|
||||||
|
fs::write(file_path, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_bellande_string(&self, data: &BellandeValue, indent: usize) -> String {
|
||||||
|
match data {
|
||||||
|
BellandeValue::Map(map) => map
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| {
|
||||||
|
let value_str = match value {
|
||||||
|
BellandeValue::Map(_) | BellandeValue::List(_) => {
|
||||||
|
format!("\n{}", self.to_bellande_string(value, indent + 2))
|
||||||
|
}
|
||||||
|
_ => format!(" {}", self.format_value(value)),
|
||||||
|
};
|
||||||
|
format!("{}{}: {}", " ".repeat(indent), key, value_str)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
|
BellandeValue::List(list) => list
|
||||||
|
.iter()
|
||||||
|
.map(|item| {
|
||||||
|
format!(
|
||||||
|
"{}- {}",
|
||||||
|
" ".repeat(indent),
|
||||||
|
self.to_bellande_string(item, indent + 2)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
|
_ => self.format_value(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_value(&self, value: &BellandeValue) -> String {
|
||||||
|
match value {
|
||||||
|
BellandeValue::String(s) => {
|
||||||
|
if s.contains(' ')
|
||||||
|
|| s.contains(':')
|
||||||
|
|| ["true", "false", "null"].contains(&s.to_lowercase().as_str())
|
||||||
|
{
|
||||||
|
format!("\"{}\"", s)
|
||||||
|
} else {
|
||||||
|
s.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BellandeValue::Integer(i) => i.to_string(),
|
||||||
|
BellandeValue::Float(f) => f.to_string(),
|
||||||
|
BellandeValue::Boolean(b) => b.to_string().to_lowercase(),
|
||||||
|
BellandeValue::Null => "null".to_string(),
|
||||||
|
BellandeValue::List(_) | BellandeValue::Map(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
git_scripts/fix_errors.sh
Executable file
31
git_scripts/fix_errors.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Get the URL from .git/config
|
||||||
|
git_url=$(git config --get remote.origin.url)
|
||||||
|
|
||||||
|
# Check if a URL is found
|
||||||
|
if [ -z "$git_url" ]; then
|
||||||
|
echo "No remote URL found in .git/config."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clone the repository into a temporary folder
|
||||||
|
git clone "$git_url" tmp_clone
|
||||||
|
|
||||||
|
# Check if the clone was successful
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
# Remove the existing .git directory if it exists
|
||||||
|
if [ -d ".git" ]; then
|
||||||
|
rm -rf .git
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy the .git directory from the clone to the current repository
|
||||||
|
cp -r tmp_clone/.git .
|
||||||
|
|
||||||
|
# Remove the clone directory
|
||||||
|
rm -rf tmp_clone
|
||||||
|
|
||||||
|
echo "Repository cloned and .git directory copied successfully."
|
||||||
|
else
|
||||||
|
echo "Failed to clone the repository."
|
||||||
|
fi
|
25
git_scripts/push.sh
Executable file
25
git_scripts/push.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Git push what is already in the repository
|
||||||
|
git pull --no-edit; git fetch;
|
||||||
|
|
||||||
|
# Exclude specific files and directories
|
||||||
|
EXCLUDES=(".git" ".gitignore" "executable")
|
||||||
|
|
||||||
|
# Find all non-hidden files and directories, excluding any hidden files and directories
|
||||||
|
find . -type f ! -path '*/.*' -print0 | while IFS= read -r -d '' file; do
|
||||||
|
# Check if the file is in the exclude list
|
||||||
|
should_exclude=false
|
||||||
|
for exclude in "${EXCLUDES[@]}"; do
|
||||||
|
if [[ "$(basename "$file")" == "$exclude" ]]; then
|
||||||
|
should_exclude=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Add file to staging area if it's not excluded
|
||||||
|
if [ "$should_exclude" = false ]; then
|
||||||
|
git add -f "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
git commit -am "latest pushes"; git push
|
110
git_scripts/repository_recal.sh
Executable file
110
git_scripts/repository_recal.sh
Executable file
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Git push what is already in the repository
|
||||||
|
git pull --no-edit; git fetch; git add .; git commit -am "latest pushes"; git push
|
||||||
|
|
||||||
|
# Get the current directory
|
||||||
|
current_dir=$(pwd)
|
||||||
|
|
||||||
|
# Read the remote repository URL from .git/config
|
||||||
|
remote_repo_url=$(git -C "$current_dir" config --get remote.origin.url)
|
||||||
|
|
||||||
|
# Create a temporary directory for cloning the repository
|
||||||
|
temp_dir=$(mktemp -d)
|
||||||
|
|
||||||
|
# Clone the repository into the temporary directory without using local references
|
||||||
|
git clone --no-local "$current_dir" "$temp_dir"
|
||||||
|
|
||||||
|
# Switch to the temporary directory
|
||||||
|
cd "$temp_dir"
|
||||||
|
|
||||||
|
# Create a temporary file to store the file list
|
||||||
|
tmp_file=$(mktemp)
|
||||||
|
# Create a temporary file to store the processed commits
|
||||||
|
processed_commits_file=$(mktemp)
|
||||||
|
|
||||||
|
# Function to check if a commit has already been processed
|
||||||
|
is_commit_processed() {
|
||||||
|
local commit="$1"
|
||||||
|
|
||||||
|
# Check if the commit is already processed
|
||||||
|
grep -Fxq "$commit" "$processed_commits_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to mark a commit as processed
|
||||||
|
mark_commit_processed() {
|
||||||
|
local commit="$1"
|
||||||
|
|
||||||
|
# Mark the commit as processed
|
||||||
|
echo "$commit" >> "$processed_commits_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if a file or folder exists in the repository
|
||||||
|
file_exists_in_repo() {
|
||||||
|
local file_path="$1"
|
||||||
|
|
||||||
|
# Check if the file or folder exists in the repository
|
||||||
|
git ls-tree --name-only -r HEAD | grep -Fxq "$file_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to process the files and folders in each commit
|
||||||
|
process_commit_files() {
|
||||||
|
local commit="$1"
|
||||||
|
|
||||||
|
# Check if the commit has already been processed
|
||||||
|
if is_commit_processed "$commit"; then
|
||||||
|
echo "Commit $commit already processed. Skipping..."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the list of files and folders in the commit (including subfolders)
|
||||||
|
git ls-tree --name-only -r "$commit" >> "$tmp_file"
|
||||||
|
|
||||||
|
# Process each file or folder in the commit
|
||||||
|
while IFS= read -r line
|
||||||
|
do
|
||||||
|
# Check if the file or folder exists in the current push
|
||||||
|
if file_exists_in_repo "$line"; then
|
||||||
|
echo "Keeping: $line"
|
||||||
|
else
|
||||||
|
echo "Deleting: $line"
|
||||||
|
git filter-repo --path "$line" --invert-paths
|
||||||
|
fi
|
||||||
|
done < "$tmp_file"
|
||||||
|
|
||||||
|
# Mark the commit as processed
|
||||||
|
mark_commit_processed "$commit"
|
||||||
|
|
||||||
|
# Clear the temporary file
|
||||||
|
> "$tmp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Iterate over each commit in the repository
|
||||||
|
git rev-list --all | while IFS= read -r commit
|
||||||
|
do
|
||||||
|
process_commit_files "$commit"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Push the filtered changes to the original repository
|
||||||
|
git remote add origin "$remote_repo_url"
|
||||||
|
git push --force origin main
|
||||||
|
|
||||||
|
# Perform a history rewrite to remove the filtered files
|
||||||
|
git filter-repo --force
|
||||||
|
|
||||||
|
# Fetch the changes from the remote repository
|
||||||
|
git -C "$current_dir" fetch origin
|
||||||
|
|
||||||
|
# Merge the remote changes into the local repository
|
||||||
|
git -C "$current_dir" merge origin/main --no-edit
|
||||||
|
|
||||||
|
# Update the local repository and reduce the size of .git if needed
|
||||||
|
git -C "$current_dir" gc --prune=now
|
||||||
|
git -C "$current_dir" reflog expire --expire=now --all
|
||||||
|
git -C "$current_dir" repack -ad
|
||||||
|
|
||||||
|
# Clean up temporary files and directories
|
||||||
|
cd "$current_dir"
|
||||||
|
rm -rf "$temp_dir"
|
||||||
|
rm "$tmp_file"
|
||||||
|
rm "$processed_commits_file"
|
Reference in New Issue
Block a user