diff --git a/.github/workflows/docker-publish-exp-image.yaml b/.github/workflows/docker-publish-exp-image.yaml index 60396cc75db..31581cebdff 100644 --- a/.github/workflows/docker-publish-exp-image.yaml +++ b/.github/workflows/docker-publish-exp-image.yaml @@ -64,7 +64,7 @@ jobs: uses: docker/build-push-action@v3 with: context: . - target: lakefs + target: lakefs-plugins push: true platforms: linux/amd64,linux/arm64,darwin/amd64,darwin/arm64 build-args: VERSION=${{ steps.version.outputs.tag }} diff --git a/.github/workflows/docker-publish.yaml b/.github/workflows/docker-publish.yaml index 43030ba9fdc..019eafc5997 100644 --- a/.github/workflows/docker-publish.yaml +++ b/.github/workflows/docker-publish.yaml @@ -82,7 +82,7 @@ jobs: uses: docker/build-push-action@v3 with: context: . - target: lakefs + target: lakefs-plugins push: true platforms: linux/amd64,linux/arm64,darwin/amd64,darwin/arm64 build-args: VERSION=${{ steps.version.outputs.tag }} diff --git a/Dockerfile b/Dockerfile index db6009dd0be..f43c2338467 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM golang:1.19.2-alpine AS build +FROM --platform=$BUILDPLATFORM golang:1.19.2-alpine3.16 AS build ARG VERSION=dev @@ -25,8 +25,33 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ GOOS=$TARGETOS GOARCH=$TARGETARCH \ go build -ldflags "-X github.com/treeverse/lakefs/pkg/version.Version=${VERSION}" -o lakectl ./cmd/lakectl +# Build delta diff binary +FROM --platform=$BUILDPLATFORM rust:1.68-alpine3.16 AS build-delta-diff-plugin +RUN apk update && apk add build-base pkgconfig openssl-dev alpine-sdk +RUN cargo new --bin delta-diff +WORKDIR /delta-diff + +# 2. Copy our manifests +COPY ./pkg/plugins/diff/delta_diff_server/Cargo.lock ./Cargo.lock +COPY ./pkg/plugins/diff/delta_diff_server/Cargo.toml ./Cargo.toml + +# 3. Build only the dependencies to cache them in this layer + +# Rust default behavior is to build a static binary (default target is -unknown-linux-musl on Alpine, and musl +# is assumed to be static). It links to openssl statically, but these are dynamic libraries. Setting RUSTFLAGS=-Ctarget-feature=-crt-static +# forces Rust to create a dynamic binary, despite asking for musl. +RUN RUSTFLAGS=-Ctarget-feature=-crt-static cargo build --release +RUN rm src/*.rs + +# 4. Now that the dependency is built, copy your source code +COPY ./pkg/plugins/diff/delta_diff_server/src ./src + +# 5. Build for release. +RUN rm ./target/release/deps/delta_diff* +RUN RUSTFLAGS=-Ctarget-feature=-crt-static cargo build --release + # lakectl image -FROM --platform=$BUILDPLATFORM alpine:3.15.0 AS lakectl +FROM --platform=$BUILDPLATFORM alpine:3.16.0 AS lakectl RUN apk add -U --no-cache ca-certificates WORKDIR /app ENV PATH /app:$PATH @@ -37,7 +62,7 @@ WORKDIR /home/lakefs ENTRYPOINT ["/app/lakectl"] # lakefs image -FROM --platform=$BUILDPLATFORM alpine:3.15.0 AS lakefs +FROM --platform=$BUILDPLATFORM alpine:3.16.0 AS lakefs-lakectl RUN apk add -U --no-cache ca-certificates # Be Docker compose friendly (i.e. support wait-for) @@ -58,3 +83,28 @@ WORKDIR /home/lakefs ENTRYPOINT ["/app/lakefs"] CMD ["run"] +# lakefs image +FROM --platform=$BUILDPLATFORM alpine:3.16.0 AS lakefs-plugins + +RUN apk add -U --no-cache ca-certificates +RUN apk add openssl-dev libc6-compat alpine-sdk +# Be Docker compose friendly (i.e. support wait-for) +RUN apk add netcat-openbsd + +WORKDIR /app +COPY ./scripts/wait-for ./ +ENV PATH /app:$PATH +COPY --from=build /build/lakefs /build/lakectl ./ +COPY --from=build-delta-diff-plugin /delta-diff/target/release/delta_diff ./ + +EXPOSE 8000/tcp + +# Setup user +RUN addgroup -S lakefs && adduser -S lakefs -G lakefs +USER lakefs +WORKDIR /home/lakefs + +RUN mkdir -p /home/lakefs/.lakefs/plugins/diff && ln -s /app/delta_diff /home/lakefs/.lakefs/plugins/diff/delta + +ENTRYPOINT ["/app/lakefs"] +CMD ["run"] diff --git a/esti/ops/docker-compose-dynamodb.yaml b/esti/ops/docker-compose-dynamodb.yaml index 665462e9548..e46067a499a 100644 --- a/esti/ops/docker-compose-dynamodb.yaml +++ b/esti/ops/docker-compose-dynamodb.yaml @@ -33,7 +33,7 @@ services: ports: - "6432:8000" esti: - image: "golang:1.19.2-alpine" + image: "golang:1.19.2-alpine3.16" links: - lakefs:s3.local.lakefs.io - lakefs:testmultipartupload.s3.local.lakefs.io diff --git a/esti/ops/docker-compose.yaml b/esti/ops/docker-compose.yaml index 370292af521..ab304345789 100644 --- a/esti/ops/docker-compose.yaml +++ b/esti/ops/docker-compose.yaml @@ -7,7 +7,7 @@ services: - "8000:8000" depends_on: - "postgres" - volumes: + volumes: - lakefs-app:/app:ro environment: - LAKEFS_AUTH_ENCRYPT_SECRET_KEY=some random secret string @@ -37,7 +37,7 @@ services: POSTGRES_USER: lakefs POSTGRES_PASSWORD: lakefs esti: - image: "golang:1.19.2-alpine" + image: "golang:1.19.2-alpine3.16" links: - lakefs:s3.local.lakefs.io - lakefs:testmultipartupload.s3.local.lakefs.io @@ -70,7 +70,7 @@ services: go test -v $ESTI_GOTEST_FLAGS ./esti --system-tests $ESTI_FLAGS --skip=".*GC" volumes: - lakefs-code:/lakefs - - lakefs-app:/app:ro + - lakefs-app:/app:ro volumes: lakefs-code: diff --git a/pkg/config/config.go b/pkg/config/config.go index 61cd9b30e56..1804ea27fc0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -80,7 +80,13 @@ type S3AuthInfo struct { // PluginProps struct holds the properties needed to run a plugin type PluginProps struct { Path string `mapstructure:"path"` - Version *int `mapstructure:"version"` + Version int `mapstructure:"version"` +} + +// Plugins struct holds the plugins dir default location and a map of optional plugin location with higher precedence +type Plugins struct { + DefaultPath string `mapstructure:"default_path"` + Properties map[string]PluginProps `mapstructure:"properties"` } // DiffProps struct holds the properties that define the details necessary to run a diff. @@ -326,8 +332,8 @@ type Config struct { Code string `mapstructure:"code"` } `mapstructure:"snippets"` } `mapstructure:"ui"` - Diff map[string]DiffProps `mapstructure:"diff"` - Plugins map[string]PluginProps `mapstructure:"plugins"` + Diff map[string]DiffProps `mapstructure:"diff"` + Plugins Plugins `mapstructure:"plugins"` } func NewConfig() (*Config, error) { diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index a5c8d426349..707ef187ee3 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -1,8 +1,6 @@ package config import ( - "fmt" - "os" "time" "github.com/spf13/viper" @@ -112,9 +110,6 @@ func setDefaults(local bool) { viper.SetDefault("graveler.commit_cache.size", 50_000) viper.SetDefault("graveler.commit_cache.expiry", 10*time.Minute) viper.SetDefault("graveler.commit_cache.jitter", 2*time.Second) -} -func DefaultPluginLocation(pluginName string) string { - hd, _ := os.UserHomeDir() - return fmt.Sprintf("%s/.lakefs/plugins/%s", hd, pluginName) + viper.SetDefault("plugins.default_path", "~/.lakefs/plugins") } diff --git a/pkg/plugins/diff/delta_diff_server/src/main.rs b/pkg/plugins/diff/delta_diff_server/src/main.rs index e7ddb6be077..0eb34236f5e 100644 --- a/pkg/plugins/diff/delta_diff_server/src/main.rs +++ b/pkg/plugins/diff/delta_diff_server/src/main.rs @@ -58,7 +58,6 @@ impl TableDiffer for DifferService { let diff_props: DiffProps = r.props.expect("Missing diff properties"); let left_table_path: TablePath = diff_props.left_table_path.expect("Missing left table's path"); let right_table_path: TablePath = diff_props.right_table_path.expect("Missing right table's path"); - let s3_config_map: HashMap = utils::construct_storage_config(s3_gateway_config_req); let left_table_res = delta_ops::get_delta_table(&s3_config_map, &diff_props.repo, &left_table_path); @@ -120,12 +119,14 @@ async fn get_diff_type(left_table_res: &Result, (Err(status), Ok(_)) => { // left table wasn't found, and it doesn't exist on the base: table created if matches!(status.code(), Code::NotFound) { - if base_table_res.is_err() && matches!(base_table_res.as_ref().unwrap_err().code(), Code::NotFound) { - Ok(DiffType::Created) - } else if base_table_res.is_ok() { // The table existed on the base branch + if base_table_res.is_err() { + if matches!(base_table_res.as_ref().unwrap_err().code(), Code::NotFound | Code::InvalidArgument) { // didn't exist in base ref or no base ref provided + Ok(DiffType::Created) + } else { // There was other kind of error with the base branch + Err(base_table_res.as_ref().unwrap_err().clone()) + } + } else { // The table existed on the base branch Ok(DiffType::Changed) - } else { // There was other kind of error with the base branch - Err(base_table_res.as_ref().unwrap_err().clone()) } } else { Err(left_table_res.as_ref().unwrap_err().clone()) @@ -166,12 +167,13 @@ impl HistoryAndVersion { } } -fn show_history(mut hist: Vec>, table_version: DeltaDataTypeVersion) -> Result, Status> { +fn show_history(mut hist: Vec>, mut table_version: DeltaDataTypeVersion) -> Result, Status> { hist.reverse(); let mut ans: Vec = Vec::with_capacity(hist.len()); for commit in hist { let table_op = construct_table_op(&commit, table_version)?; ans.push(table_op); + table_version -= 1; } Ok(ans) } diff --git a/pkg/plugins/diff/service.go b/pkg/plugins/diff/service.go index 3c1e01f8405..6c3c2aef0a7 100644 --- a/pkg/plugins/diff/service.go +++ b/pkg/plugins/diff/service.go @@ -3,10 +3,14 @@ package tablediff import ( "context" "errors" + "os" + "path/filepath" "strings" "sync" "time" + "github.com/mitchellh/go-homedir" + "github.com/treeverse/lakefs/pkg/config" "github.com/treeverse/lakefs/pkg/logging" "github.com/treeverse/lakefs/pkg/plugins" @@ -133,7 +137,7 @@ func (s *Service) appendClosingFunction(diffType string, f func()) { } // NewService is used to initialize a new Differ service. The returned function is a closing function for the service. -func NewService(diffProps map[string]config.DiffProps, pluginProps map[string]config.PluginProps) (*Service, func()) { +func NewService(diffProps map[string]config.DiffProps, pluginProps config.Plugins) (*Service, func()) { service := &Service{ pluginHandler: internal.NewManager[Differ](), closeFunctions: make(map[string]func()), @@ -142,16 +146,22 @@ func NewService(diffProps map[string]config.DiffProps, pluginProps map[string]co return service, service.Close } -func registerPlugins(service *Service, diffProps map[string]config.DiffProps, pluginProps map[string]config.PluginProps) { +func registerPlugins(service *Service, diffProps map[string]config.DiffProps, pluginProps config.Plugins) { + registerDefaultPlugins(service, pluginProps.DefaultPath) for n, p := range diffProps { pluginName := p.PluginName // If the requested plugin wasn't configured with a path, it will be defined under the default location - pluginPath := config.DefaultPluginLocation(pluginName) + pluginPath := filepath.Join(diffPluginsDefaultPath(pluginProps.DefaultPath), pluginName) pluginVersion := 1 // default version - if props, ok := pluginProps[pluginName]; ok { - pluginPath = props.Path - if props.Version != nil { - pluginVersion = *props.Version + if props, ok := pluginProps.Properties[pluginName]; ok { + pp, err := homedir.Expand(props.Path) + if err != nil { + logging.Default().Errorf("failed to register a plugin for an invalid path: '%s'", props.Path) + continue + } + pluginPath = pp + if props.Version != 0 { + pluginVersion = props.Version } } @@ -166,3 +176,24 @@ func registerPlugins(service *Service, diffProps map[string]config.DiffProps, pl logging.Default().Infof("successfully registered a plugin for diff type: '%s'", n) } } + +func registerDefaultPlugins(service *Service, pluginsPath string) { + diffPluginsDir := diffPluginsDefaultPath(pluginsPath) + deltaPath := filepath.Join(diffPluginsDir, "delta") + _, err := os.Stat(deltaPath) + if err != nil { + if !os.IsNotExist(err) { + logging.Default().WithError(err).Error("failed to access delta lake diff plugin") + } + return + } + + pid := plugins.PluginIdentity{ProtocolVersion: 1, ExecutableLocation: deltaPath} + pa := plugins.PluginHandshake{} + RegisterDeltaLakeDiffPlugin(service, pid, pa) +} + +func diffPluginsDefaultPath(pluginsPath string) string { + pp, _ := homedir.Expand(pluginsPath) + return filepath.Join(pp, "diff") +} diff --git a/pkg/plugins/diff/service_test.go b/pkg/plugins/diff/service_test.go index 3236e731e23..8cddf558700 100644 --- a/pkg/plugins/diff/service_test.go +++ b/pkg/plugins/diff/service_test.go @@ -3,6 +3,7 @@ package tablediff import ( "context" "errors" + "path/filepath" "strconv" "testing" @@ -59,7 +60,7 @@ func Test_registerPlugins(t *testing.T) { type args struct { service *Service diffProps map[string]config.DiffProps - pluginProps map[string]config.PluginProps + pluginProps config.Plugins } testCases := []struct { description string @@ -71,6 +72,7 @@ func Test_registerPlugins(t *testing.T) { { description: "register delta diff plugin - default path and version - success", diffTypes: []string{"delta"}, + pluginName: pluginName, args: args{ service: NewMockService(), diffProps: map[string]config.DiffProps{ @@ -78,7 +80,7 @@ func Test_registerPlugins(t *testing.T) { PluginName: pluginName, }, }, - pluginProps: nil, + pluginProps: config.Plugins{}, }, }, { @@ -92,10 +94,13 @@ func Test_registerPlugins(t *testing.T) { PluginName: pluginName, }, }, - pluginProps: map[string]config.PluginProps{ - pluginName: { - Path: customPluginPath, - Version: &customPluginVersion, + pluginProps: config.Plugins{ + DefaultPath: "", + Properties: map[string]config.PluginProps{ + pluginName: { + Path: customPluginPath, + Version: customPluginVersion, + }, }, }, }, @@ -116,7 +121,7 @@ func Test_registerPlugins(t *testing.T) { PluginName: pluginName, }, }, - pluginProps: nil, + pluginProps: config.Plugins{}, }, expectedErr: ErrNotFound, }, @@ -134,10 +139,13 @@ func Test_registerPlugins(t *testing.T) { PluginName: pluginName, }, }, - pluginProps: map[string]config.PluginProps{ - pluginName: { - Path: customPluginPath, - Version: &customPluginVersion, + pluginProps: config.Plugins{ + DefaultPath: "", + Properties: map[string]config.PluginProps{ + pluginName: { + Path: customPluginPath, + Version: customPluginVersion, + }, }, }, }, @@ -157,9 +165,9 @@ func Test_registerPlugins(t *testing.T) { t.Errorf("'%s' failed: %s", tc.description, err) } pluginDetails := diffs.Diffs[0].OperationContent - tcPath := config.DefaultPluginLocation(tc.args.diffProps[dt].PluginName) - if tc.args.pluginProps[tc.pluginName].Path != "" { - tcPath = tc.args.pluginProps[tc.pluginName].Path + tcPath := filepath.Join(tc.args.pluginProps.DefaultPath, "diff", tc.pluginName) + if tc.args.pluginProps.Properties[tc.pluginName].Path != "" { + tcPath = tc.args.pluginProps.Properties[tc.pluginName].Path } if pluginDetails[PluginPath] != tcPath { t.Errorf("'%s' failed: incorrect plugin path. got '%s' instead of '%s'", @@ -167,12 +175,12 @@ func Test_registerPlugins(t *testing.T) { pluginDetails[PluginPath], tcPath) } - tcVersion := tc.args.pluginProps[tc.pluginName].Version - if tcVersion != nil && pluginDetails[PluginVersion] != strconv.Itoa(*tcVersion) { + tcVersion := tc.args.pluginProps.Properties[tc.pluginName].Version + if tcVersion != 0 && pluginDetails[PluginVersion] != strconv.Itoa(tcVersion) { t.Errorf("'%s' failed: incorrect plugin version. got '%s' instead of '%s'", tc.description, pluginDetails[PluginVersion], - strconv.Itoa(*tcVersion)) + strconv.Itoa(tcVersion)) } } } diff --git a/webui/src/lib/components/repository/changes.jsx b/webui/src/lib/components/repository/changes.jsx index 4fc8ae75e13..2f0a7bc1dd8 100644 --- a/webui/src/lib/components/repository/changes.jsx +++ b/webui/src/lib/components/repository/changes.jsx @@ -1,22 +1,18 @@ import React, {useCallback, useEffect, useState} from "react"; -import { - ArrowLeftIcon, - ClockIcon, DiffIcon, InfoIcon, PlusIcon, XIcon -} from "@primer/octicons-react"; +import {ArrowLeftIcon, ClockIcon, InfoIcon, PlusIcon, XIcon} from "@primer/octicons-react"; import {useAPI, useAPIWithPagination} from "../../hooks/api"; -import {Error, ExperimentalOverlayTooltip} from "../controls"; +import {Error} from "../controls"; import {ObjectsDiff} from "./ObjectsDiff"; import {TreeItemType} from "../../../constants"; import * as tablesUtil from "../../../util/tablesUtil"; import {ObjectTreeEntryRow, PrefixTreeEntryRow, TableTreeEntryRow} from "./treeRows"; import Alert from "react-bootstrap/Alert"; -import {ComingSoonModal} from "../modals"; import Button from "react-bootstrap/Button"; import Card from "react-bootstrap/Card"; import Table from "react-bootstrap/Table"; -import {refs, statistics} from "../../api"; +import {refs} from "../../api"; import {DeltaLakeDiff} from "./TableDiff"; import Form from "react-bootstrap/Form"; import Row from "react-bootstrap/Row"; @@ -44,7 +40,6 @@ export const TreeItemRow = ({ entry, repo, reference, leftDiffRefID, rightDiffRe const [afterUpdated, setAfterUpdated] = useState(""); // state of pagination of the item's children const [resultsState, setResultsState] = useState({results:[], pagination:{}}); // current retrieved children of the item const [diffExpanded, setDiffExpanded] = useState(false); // state of a leaf item expansion - const enableDeltaDiff = JSON.parse(localStorage.getItem(`enable_delta_diff`)); const itemType = useTreeItemType(entry, repo, leftDiffRefID, rightDiffRefID); @@ -90,7 +85,7 @@ export const TreeItemRow = ({ entry, repo, reference, leftDiffRefID, rightDiffRe } - } else if (itemType.type === TreeItemType.Prefix || !enableDeltaDiff) { + } else if (itemType.type === TreeItemType.Prefix) { return <> setDirExpanded(!dirExpanded)} onRevert={onRevert} onNavigate={onNavigate} getMore={getMore} repo={repo} reference={reference}/> {dirExpanded && results && @@ -163,7 +158,6 @@ function useTreeItemType(entry, repo, leftDiffRefID, rightDiffRefID) { * and uncommitted changes views. * * @param results to be displayed in the changes tree container - * @param showExperimentalDeltaDiffButton whether or not to display a delta-specific experimental feature button. TODO (Tals): remove when enabling the delta diff feature. * @param delimiter objects delimiter ('' or '/') * @param uriNavigator to navigate in the page using the changes container * @param leftDiffRefID commitID / branch @@ -179,11 +173,10 @@ function useTreeItemType(entry, repo, leftDiffRefID, rightDiffRefID) { * @param onNavigate to be called when navigating to a prefix * @param onRevert to be called when an object/prefix is requested to be reverted */ -export const ChangesTreeContainer = ({results, showExperimentalDeltaDiffButton = false, delimiter, uriNavigator, +export const ChangesTreeContainer = ({results, delimiter, uriNavigator, leftDiffRefID, rightDiffRefID, repo, reference, internalRefresh, prefix, getMore, loading, nextPage, setAfterUpdated, onNavigate, onRevert, setIsTableMerge, changesTreeMessage= ""}) => { - const enableDeltaDiff = JSON.parse(localStorage.getItem(`enable_delta_diff`)); const [tableDiffState, setTableDiffState] = useState({isShown: false, expandedTablePath: "", expandedTableName: ""}); if (results.length === 0) { @@ -192,9 +185,7 @@ export const ChangesTreeContainer = ({results, showExperimentalDeltaDiffButton = } else { return
- {!enableDeltaDiff - ? - : tableDiffState.isShown + {tableDiffState.isShown ? - - -} - export const MetadataFields = ({ metadataFields, setMetadataFields}) => { const onChangeKey = useCallback((i) => { return e => { @@ -350,4 +309,4 @@ export const MetadataFields = ({ metadataFields, setMetadataFields}) => {
) -} \ No newline at end of file +} diff --git a/webui/src/lib/components/repository/treeRows.jsx b/webui/src/lib/components/repository/treeRows.jsx index 40287548033..29585a01d8d 100644 --- a/webui/src/lib/components/repository/treeRows.jsx +++ b/webui/src/lib/components/repository/treeRows.jsx @@ -104,7 +104,7 @@ export const TableTreeEntryRow = ({entry, relativeTo = "", onClickExpandDiff, de const diffIndicator = const rowActions = [] - rowActions.push(new RowAction(null, null, "Show table changes", onClickExpandDiff)) + rowActions.push(new RowAction(null, "", "Show table changes", onClickExpandDiff)) if (onRevert) { rowActions.push(new RowAction(, "Revert changes", null, () => { setShowRevertConfirm(true) diff --git a/webui/src/pages/repositories/repository/changes.jsx b/webui/src/pages/repositories/repository/changes.jsx index c95e817f55d..a8d9c590f72 100644 --- a/webui/src/pages/repositories/repository/changes.jsx +++ b/webui/src/pages/repositories/repository/changes.jsx @@ -1,9 +1,6 @@ import React, {useRef, useState} from "react"; -import { - GitCommitIcon, - HistoryIcon, -} from "@primer/octicons-react"; +import {GitCommitIcon, HistoryIcon,} from "@primer/octicons-react"; import Modal from "react-bootstrap/Modal"; import Form from "react-bootstrap/Form"; @@ -11,7 +8,7 @@ import Form from "react-bootstrap/Form"; import Alert from "react-bootstrap/Alert"; import Button from "react-bootstrap/Button"; -import {refs, branches, commits} from "../../../lib/api"; +import {branches, commits, refs} from "../../../lib/api"; import {useAPIWithPagination} from "../../../lib/hooks/api"; import {RefContextProvider, useRefs} from "../../../lib/hooks/repo"; import {ConfirmationModal} from "../../../lib/components/modals"; @@ -269,4 +266,4 @@ const RepositoryChangesPage = () => { ) } -export default RepositoryChangesPage; \ No newline at end of file +export default RepositoryChangesPage; diff --git a/webui/src/pages/repositories/repository/compare.jsx b/webui/src/pages/repositories/repository/compare.jsx index 1644f5dd675..0c44584bf48 100644 --- a/webui/src/pages/repositories/repository/compare.jsx +++ b/webui/src/pages/repositories/repository/compare.jsx @@ -1,16 +1,10 @@ import React, {useCallback, useState} from "react"; import {RepositoryPageLayout} from "../../../lib/components/repository/layout"; -import { - ActionGroup, - ActionsBar, - Error, - Loading, - RefreshButton -} from "../../../lib/components/controls"; +import {ActionGroup, ActionsBar, Error, Loading, RefreshButton} from "../../../lib/components/controls"; import {RefContextProvider, useRefs} from "../../../lib/hooks/repo"; import RefDropdown from "../../../lib/components/repository/refDropdown"; -import {ArrowLeftIcon, GitMergeIcon, ArrowSwitchIcon} from "@primer/octicons-react"; +import {ArrowLeftIcon, ArrowSwitchIcon, GitMergeIcon} from "@primer/octicons-react"; import {useAPIWithPagination} from "../../../lib/hooks/api"; import {refs, statistics} from "../../../lib/api"; import Alert from "react-bootstrap/Alert"; @@ -104,20 +98,26 @@ const CompareList = ({ repo, reference, compareReference, prefix, onSelectRef, o rightCommittedRef += "@"; } - if (loading) content = + if (loading) { + content = + } else if (error) content = - else if (compareReference.id === reference.id) content = ( - - There isn’t anything to compare. - You’ll need to use two different sources to get a valid comparison. - - ) - else content = + else if (compareReference.id === reference.id) { + content = ( + + There isn’t anything to compare. + You’ll need to use two different sources to get a valid comparison. + + ) + } + else { + content = + } const emptyDiff = (!loading && !error && !!results && results.length === 0); diff --git a/webui/src/styles/globals.css b/webui/src/styles/globals.css index a8560b0d391..c732b47cf87 100644 --- a/webui/src/styles/globals.css +++ b/webui/src/styles/globals.css @@ -347,7 +347,7 @@ td.tree-path { } .table .change-entry-row .change-entry-row-actions .btn-link, -.table .tree-entry-row .change-entry-row-actions .btn-link { +.table .tree-entry-row .change-entry-row-actions .btn-link .btn-link:hover { visibility: hidden; font-size: 0.875rem; padding: 5px; diff --git a/webui/src/util/tablesUtil.jsx b/webui/src/util/tablesUtil.jsx index 497e5678232..3e36e086664 100644 --- a/webui/src/util/tablesUtil.jsx +++ b/webui/src/util/tablesUtil.jsx @@ -9,17 +9,10 @@ import {objects} from "../lib/api"; * @return true if the path is a delat table root, false otherwise. */ export async function isDeltaLakeTable(entry, repo, ref) { - const enableDeltaDiff = JSON.parse(localStorage.getItem(`enable_delta_diff`)); - if (entry.path_type === "object") { return } - if (enableDeltaDiff) { - let response = await objects.list(repo.id, ref, entry.path + "_delta_log/") - if (response !== null && response.results.length !== 0) { - return true; - } - } - return false; + let response = await objects.list(repo.id, ref, entry.path + "_delta_log/") + return response !== null && response.results.length !== 0; }