Crie seu própio Github!
Introdução
Hoje em dia o Github certamente é a maior plataforma de hospedagem de código do mundo. Mas existem algumas alternativas notáveis como o Gitlab e o BitBucket. Além de algumas alternativas completamente open source (além do GitLab), como o Gitea.
Mas e que tal criar a sua própia alternativa ao Github? Provavelmente você não vai querer reinventar a roda, mas pode ser um projetinho interessante, não acha?
Aqui nos vamos utilizar Javascript e Nodejs, utilizando a biblioteca node-git-server, para não termos que nos preocupar de como é a implemetação de um servidor git (mas caso você queria, pode dar uma olhada na documentação oficial do git). Você pode tentar procurar implementações na sua linguagem favorita, em encontrei algumas em Python. Uma que utiliza Flask e outra que utiliza FastAPI (nesse caso são implementações, não bibliotecas que abstream a utilização. Mas verifiquei o código fonte e ambas são bem simples de entender e modificar). Também vou considerar que você já tem o conhecimento básico de Javascript, Nodejs e Git.
Instalação
Você vai precisar do Nodejs e do Git. Nada mais.
Criação do projeto
Nosso servidor vai ter o seguinte código:
import { Git } from "node-git-server"
import { join } from "path"
const repos = new Git(join(__dirname, "./repos"), { autoCreate: true })
repos.on("push", (push) => {
console.log(`push ${push.repo}/${push.commit} ( ${push.branch} )`)
push.accept()
})
repos.on("fetch", (fetch) => {
console.log(`fetch ${fetch.commit}`)
fetch.accept()
})
repos.listen(8000, { type: "http" }, () => {
console.log("Running at http://localhost:8000")
})
Pronto! já temos um servidor de git rodando, você pode testar clonando um repositório:
>> git clone http://localhost:8000/test
Cloning into 'test'...
warning: You appear to have cloned an empty repository.
Como passamos o parâmetro autoCreate: true
na criação do objeto repos
, ele automaticamente irá criar o repositório caso ele não exista.
Podemos adicionar autenticação ao nosso servidor, passando o parâmetro authenticate
:
const repos = new Git(join(__dirname, "./repos"), {
autoCreate: true,
authenticate: ({ type, user }, next) => {
if (type == "push") {
user((username, password) => {
if (username === "username" && password === "password") {
next()
} else {
next(new Error("Invalid username or password"))
}
})
} else {
next()
}
}
})
Agora, se rodarmos novamente, quando pedirmos para fazer um push, ele irá pedir o usuário e a senha:
>> git push
Username for 'http://localhost:8000': username
Password for 'http://username@localhost:8000':
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 210 bytes | 210.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To http://localhost:8000/test
* [new branch] main -> main
Nesse caso, ele apenas vai verificar se o usuário e senha correspondem respectivamente a "username" e "password", mas você costumizar a autenticação como quiser, por exemplo verificando se o usuário existe em um banco de dados, e pedir a autenticação para todas as ações (clone, pull, etc), para fazer um repositório 100% privado.
O node-git-server
tem mais algumas funções como o envio de logs para o cliente, como você pode conferir na documentação.
Pro hoje é isso, isso é apenas o básico, talvez eu possa fazer fazer uma série criando de fato um clone do Github, com interface gráfica e várias das funcionalidades...
Qualquer dúvida ou sugestão podem colocar nos comentários ;)