Skip to content

Commit f61d19e

Browse files
committed
feat: configure branch dropdown (wip)
1 parent 6a88906 commit f61d19e

File tree

7 files changed

+172
-26
lines changed

7 files changed

+172
-26
lines changed

modules/nessie/client.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package nessie
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"time"
8+
"code.gitea.io/gitea/modules/setting"
9+
"code.gitea.io/gitea/modules/log"
10+
11+
)
12+
13+
type Reference struct {
14+
Name string `json:"name"`
15+
Hash string `json:"hash"`
16+
Type string `json:"type"`
17+
}
18+
19+
// ReferencesResponse represents the Nessie API response structure
20+
type ReferencesResponse struct {
21+
Token *string `json:"token"`
22+
References []Reference `json:"references"`
23+
HasMore bool `json:"hasMore"`
24+
}
25+
26+
type Client struct {
27+
baseURL string
28+
authToken string
29+
httpClient *http.Client
30+
}
31+
32+
func NewClient() *Client {
33+
return &Client{
34+
baseURL: setting.Nessie.APIURL,
35+
authToken: setting.Nessie.AuthToken,
36+
httpClient: &http.Client{Timeout: 10 * time.Second},
37+
}
38+
}
39+
40+
func (c *Client) GetAllReferences(repo string) ([]Reference, error) {
41+
// TODO: figure out how to handle multiple repositories
42+
url := fmt.Sprintf("%s/api/v1/trees/", c.baseURL)
43+
44+
req, err := http.NewRequest("GET", url, nil)
45+
if err != nil {
46+
return nil, fmt.Errorf("failed to create request: %v", err)
47+
}
48+
49+
if c.authToken != "" {
50+
req.Header.Set("Authorization", "Bearer "+c.authToken)
51+
}
52+
53+
resp, err := c.httpClient.Do(req)
54+
if err != nil {
55+
return nil, fmt.Errorf("failed to make request: %v", err)
56+
}
57+
defer resp.Body.Close()
58+
59+
if resp.StatusCode != http.StatusOK {
60+
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
61+
}
62+
63+
var response ReferencesResponse
64+
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
65+
return nil, fmt.Errorf("failed to decode response: %v", err)
66+
}
67+
log.Info("Nessie references: %v", response.References)
68+
return response.References, nil
69+
}

modules/setting/nessie.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package setting
2+
3+
import (
4+
"code.gitea.io/gitea/modules/log"
5+
)
6+
7+
var Nessie = struct {
8+
Enabled bool
9+
APIURL string
10+
DefaultBranch string
11+
AuthToken string
12+
}{
13+
Enabled: true,
14+
APIURL: "http://localhost:19120",
15+
DefaultBranch: "main",
16+
AuthToken: "",
17+
}
18+
19+
func loadNessieFrom(rootCfg ConfigProvider) {
20+
if err := rootCfg.Section("nessie").MapTo(&Nessie); err != nil {
21+
log.Fatal("Failed to map Nessie settings: %v", err)
22+
}
23+
}

nessie-stack/notebooks/test.ipynb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"name": "stderr",
1010
"output_type": "stream",
1111
"text": [
12-
"25/03/22 00:13:18 WARN SparkSession: Using an existing Spark session; only runtime SQL configurations will take effect.\n"
12+
"25/03/23 21:11:07 WARN SparkSession: Using an existing Spark session; only runtime SQL configurations will take effect.\n"
1313
]
1414
}
1515
],
@@ -28,14 +28,12 @@
2828
"data": {
2929
"text/plain": [
3030
"[('spark.sql.catalog.nessie', 'org.apache.iceberg.spark.SparkCatalog'),\n",
31-
" ('spark.app.submitTime', '1742601784570'),\n",
3231
" ('spark.sql.catalog.nessie.uri', 'http://nessie:19120/api/v1'),\n",
3332
" ('spark.hadoop.fs.s3a.path.style.access', 'true'),\n",
3433
" ('spark.sql.catalog.nessie.ref', 'main'),\n",
35-
" ('spark.app.startTime', '1742601784818'),\n",
36-
" ('spark.driver.port', '39441'),\n",
3734
" ('spark.sql.warehouse.dir',\n",
3835
" 'file:/home/iceberg/notebooks/notebooks/spark-warehouse'),\n",
36+
" ('spark.app.submitTime', '1742764264501'),\n",
3937
" ('spark.hadoop.fs.s3a.access.key', 'minioadmin'),\n",
4038
" ('spark.sql.catalog.nessie.s3.path-style-access', 'true'),\n",
4139
" ('spark.serializer.objectStreamReset', '100'),\n",
@@ -50,14 +48,15 @@
5048
" 'file:///root/.ivy2/jars/org.apache.iceberg_iceberg-spark-runtime-3.5_2.12-1.8.1.jar,file:///root/.ivy2/jars/org.projectnessie.nessie-integrations_nessie-spark-extensions-3.5_2.12-0.103.2.jar'),\n",
5149
" ('spark.driver.extraJavaOptions',\n",
5250
" '-Djava.net.preferIPv6Addresses=false -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/sun.nio.cs=ALL-UNNAMED --add-opens=java.base/sun.security.action=ALL-UNNAMED --add-opens=java.base/sun.util.calendar=ALL-UNNAMED --add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED -Djdk.reflect.useDirectMethodHandle=false'),\n",
53-
" ('spark.app.id', 'local-1742601785395'),\n",
51+
" ('spark.app.startTime', '1742764264699'),\n",
5452
" ('spark.sql.catalog.nessie.s3.endpoint', 'http://minio:9000'),\n",
53+
" ('spark.app.id', 'local-1742764265168'),\n",
5554
" ('spark.repl.local.jars',\n",
5655
" 'file:///root/.ivy2/jars/org.apache.iceberg_iceberg-spark-runtime-3.5_2.12-1.8.1.jar,file:///root/.ivy2/jars/org.projectnessie.nessie-integrations_nessie-spark-extensions-3.5_2.12-0.103.2.jar'),\n",
5756
" ('spark.executor.id', 'driver'),\n",
58-
" ('spark.driver.host', '876c347e2cee'),\n",
5957
" ('spark.app.name', 'PySparkShell'),\n",
6058
" ('spark.hadoop.fs.s3a.impl', 'org.apache.hadoop.fs.s3a.S3AFileSystem'),\n",
59+
" ('spark.driver.host', '137a0ca84ad6'),\n",
6160
" ('spark.sql.catalogImplementation', 'hive'),\n",
6261
" ('spark.sql.catalog.nessie.io-impl', 'org.apache.iceberg.aws.s3.S3FileIO'),\n",
6362
" ('spark.submit.pyFiles',\n",
@@ -66,14 +65,15 @@
6665
" ('spark.executor.extraJavaOptions',\n",
6766
" '-Djava.net.preferIPv6Addresses=false -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/sun.nio.cs=ALL-UNNAMED --add-opens=java.base/sun.security.action=ALL-UNNAMED --add-opens=java.base/sun.util.calendar=ALL-UNNAMED --add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED -Djdk.reflect.useDirectMethodHandle=false'),\n",
6867
" ('spark.sql.catalog.nessie.warehouse', 's3a://warehouse'),\n",
68+
" ('spark.app.initial.jar.urls',\n",
69+
" 'spark://137a0ca84ad6:46315/jars/org.projectnessie.nessie-integrations_nessie-spark-extensions-3.5_2.12-0.103.2.jar,spark://137a0ca84ad6:46315/jars/org.apache.iceberg_iceberg-spark-runtime-3.5_2.12-1.8.1.jar'),\n",
6970
" ('spark.jars',\n",
7071
" 'file:///root/.ivy2/jars/org.apache.iceberg_iceberg-spark-runtime-3.5_2.12-1.8.1.jar,file:///root/.ivy2/jars/org.projectnessie.nessie-integrations_nessie-spark-extensions-3.5_2.12-0.103.2.jar'),\n",
7172
" ('spark.hadoop.fs.s3a.endpoint', 'http://minio:9000'),\n",
73+
" ('spark.driver.port', '46315'),\n",
74+
" ('spark.sql.catalog.nessie.type', 'nessie'),\n",
7275
" ('spark.files',\n",
7376
" 'file:///root/.ivy2/jars/org.apache.iceberg_iceberg-spark-runtime-3.5_2.12-1.8.1.jar,file:///root/.ivy2/jars/org.projectnessie.nessie-integrations_nessie-spark-extensions-3.5_2.12-0.103.2.jar'),\n",
74-
" ('spark.sql.catalog.nessie.type', 'nessie'),\n",
75-
" ('spark.app.initial.jar.urls',\n",
76-
" 'spark://876c347e2cee:39441/jars/org.apache.iceberg_iceberg-spark-runtime-3.5_2.12-1.8.1.jar,spark://876c347e2cee:39441/jars/org.projectnessie.nessie-integrations_nessie-spark-extensions-3.5_2.12-0.103.2.jar'),\n",
7777
" ('spark.ui.showConsoleProgress', 'true')]"
7878
]
7979
},
@@ -95,11 +95,11 @@
9595
"name": "stderr",
9696
"output_type": "stream",
9797
"text": [
98-
"25/03/22 00:13:22 WARN HiveConf: HiveConf of name hive.stats.jdbc.timeout does not exist\n",
99-
"25/03/22 00:13:22 WARN HiveConf: HiveConf of name hive.stats.retries.wait does not exist\n",
100-
"25/03/22 00:13:22 WARN ObjectStore: Version information not found in metastore. hive.metastore.schema.verification is not enabled so recording the schema version 2.3.0\n",
101-
"25/03/22 00:13:22 WARN ObjectStore: setMetaStoreSchemaVersion called but recording version is disabled: version = 2.3.0, comment = Set by MetaStore [email protected]\n",
102-
"25/03/22 00:13:23 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException\n"
98+
"25/03/23 21:11:15 WARN HiveConf: HiveConf of name hive.stats.jdbc.timeout does not exist\n",
99+
"25/03/23 21:11:15 WARN HiveConf: HiveConf of name hive.stats.retries.wait does not exist\n",
100+
"25/03/23 21:11:16 WARN ObjectStore: Version information not found in metastore. hive.metastore.schema.verification is not enabled so recording the schema version 2.3.0\n",
101+
"25/03/23 21:11:16 WARN ObjectStore: setMetaStoreSchemaVersion called but recording version is disabled: version = 2.3.0, comment = Set by MetaStore [email protected]\n",
102+
"25/03/23 21:11:16 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException\n"
103103
]
104104
},
105105
{
@@ -138,7 +138,7 @@
138138
}
139139
],
140140
"source": [
141-
"spark.sql(\"create namespace default\")"
141+
"spark.sql(\"CREATE BRANCH te\")"
142142
]
143143
},
144144
{

options/locale/locale_en-US.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,13 @@ visibility.private_tooltip = Visible only to members of organizations you have j
10251025

10261026
[repo]
10271027
catalog = Catalog
1028+
catalog.overview = Data catalog Overview
1029+
catalog.datasets = Datasets
1030+
catalog.tags = Tags
1031+
catalog.new_dataset = New Dataset
1032+
catalog.updated = Updated
1033+
catalog.popular_tags = Popular Tags
1034+
10281035
new_repo_helper = A repository contains all project files, including revision history. Already hosting one elsewhere? <a href="%s">Migrate repository.</a>
10291036
owner = Owner
10301037
owner_helper = Some organizations may not show up in the dropdown due to a maximum repository count limit.

routers/web/repo/view.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"code.gitea.io/gitea/modules/lfs"
3434
"code.gitea.io/gitea/modules/log"
3535
"code.gitea.io/gitea/modules/markup"
36+
"code.gitea.io/gitea/modules/nessie"
3637
"code.gitea.io/gitea/modules/setting"
3738
"code.gitea.io/gitea/modules/structs"
3839
"code.gitea.io/gitea/modules/templates"
@@ -389,8 +390,24 @@ func Forks(ctx *context.Context) {
389390
ctx.HTML(http.StatusOK, tplForks)
390391
}
391392

392-
// CatalogHome renders the repository catalog home/overview page
393393
func CatalogHome(ctx *context.Context) {
394394
ctx.Data["PageIsCatalog"] = true
395+
396+
// Initialize Nessie client
397+
client := nessie.NewClient()
398+
399+
// Get references from Nessie
400+
refs, err := client.GetAllReferences(ctx.Repo.Repository.Name)
401+
if err != nil {
402+
ctx.ServerError("GetAllReferences", err)
403+
return
404+
}
405+
log.Info("Current branch: %s", ctx.Repo.BranchName)
406+
ctx.Data["NessieRefs"] = refs
407+
ctx.Data["CurrentBranch"] = ctx.Repo.BranchName // or get from query parameter
408+
if ctx.Data["CurrentBranch"] == "" {
409+
ctx.Data["CurrentBranch"] = setting.Nessie.DefaultBranch // or your default branch
410+
}
411+
395412
ctx.HTML(http.StatusOK, tplCatalog)
396413
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<div class="ui dropdown custom">
2+
<button class="ui basic button nessie-branch-button">
3+
{{svg "octicon-git-branch"}} <span class="text">{{.CurrentBranch}}</span>
4+
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
5+
</button>
6+
<div class="menu">
7+
<div class="ui icon search input">
8+
<i class="icon">{{svg "octicon-search" 16}}</i>
9+
<input name="search" placeholder="{{ctx.Locale.Tr "repo.filter_branch_and_tag"}}...">
10+
</div>
11+
<div class="header">
12+
<div class="ui grid">
13+
<div class="eight wide column">
14+
{{ctx.Locale.Tr "repo.branches"}}
15+
</div>
16+
<div class="eight wide column">
17+
{{ctx.Locale.Tr "repo.tags"}}
18+
</div>
19+
</div>
20+
</div>
21+
<div class="scrolling menu">
22+
{{range .NessieRefs}}
23+
<a class="{{if eq $.CurrentBranch .Name}}active selected{{end}} item" href="{{$.RepoLink}}/catalog/{{.Type}}/{{.Name}}">
24+
{{if eq .Type "branch"}}
25+
{{svg "octicon-git-branch"}}
26+
{{else}}
27+
{{svg "octicon-tag"}}
28+
{{end}}
29+
<span class="text">{{.Name}}</span>
30+
<span class="text small">{{.Hash}}</span>
31+
</a>
32+
{{end}}
33+
</div>
34+
</div>
35+
</div>

templates/repo/catalog/view_content.tmpl

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
{{template "repo/sub_menu" .}}
22
<div class="repo-button-row">
33
<div class="repo-button-row-left">
4-
{{template "repo/branch_dropdown" dict
5-
"Repository" .Repository
6-
"ShowTabBranches" true
7-
"ShowTabTags" true
8-
"CurrentRefType" .RefFullName.RefType
9-
"CurrentRefShortName" .RefFullName.ShortName
10-
"CurrentTreePath" .TreePath
11-
"RefLinkTemplate" "{RepoLink}/catalog/{RefType}/{RefShortName}/{TreePath}"
12-
"AllowCreateNewRef" .CanCreateBranch
13-
"ShowViewAllRefsEntry" true
4+
{{template "repo/catalog/branch_dropdown" dict
5+
"ctx" .ctx
6+
"RepoLink" .RepoLink
7+
"CurrentBranch" .CurrentBranch
8+
"NessieRefs" .NessieRefs
149
}}
1510

1611
<a href="{{.Repository.Link}}/catalog/find" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_dataset"}}</a>

0 commit comments

Comments
 (0)