Skip to content

Commit

Permalink
Merge pull request #14951 from iterate-ch/bugfix/GH-14936
Browse files Browse the repository at this point in the history
Allow tilde to denote home directory in default path.
  • Loading branch information
ylangisc authored Aug 3, 2023
2 parents 16a0157 + f8b550b commit f7e5329
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 34 deletions.
4 changes: 2 additions & 2 deletions cli/src/main/java/ch/cyberduck/cli/Terminal.java
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ public void uncaughtException(final Thread t, final Throwable e) {
final Path remote;
if(StringUtils.startsWith(new CommandLinePathParser(input, protocols).parse(uri).getAbsolute(), TildePathExpander.PREFIX)) {
final Path home = this.execute(new TerminalBackgroundAction<>(controller, source, new HomeFinderWorker()));
remote = new TildePathExpander(home).expand(new CommandLinePathParser(input, protocols).parse(uri));
remote = new Path(new TildePathExpander(home).expand(new CommandLinePathParser(input, protocols).parse(uri).getAbsolute()), EnumSet.of(Path.Type.directory));
}
else {
remote = new CommandLinePathParser(input, protocols).parse(uri);
Expand All @@ -293,7 +293,7 @@ public void uncaughtException(final Thread t, final Throwable e) {
final Path vault;
if(StringUtils.startsWith(input.getOptionValue(action.name()), TildePathExpander.PREFIX)) {
final Path home = this.execute(new TerminalBackgroundAction<>(controller, source, new HomeFinderWorker()));
vault = new TildePathExpander(home).expand(new Path(input.getOptionValue(action.name()), EnumSet.of(Path.Type.directory, Path.Type.vault)));
vault = new Path(new TildePathExpander(home).expand(input.getOptionValue(action.name())), EnumSet.of(Path.Type.directory, Path.Type.vault));
}
else {
vault = new Path(input.getOptionValue(TerminalOptionsBuilder.Params.vault.name()), EnumSet.of(Path.Type.directory, Path.Type.vault));
Expand Down
16 changes: 10 additions & 6 deletions core/src/main/java/ch/cyberduck/core/TildePathExpander.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,26 @@
public class TildePathExpander {

public static final String PREFIX
= String.format("%s%s", Path.DELIMITER, Path.HOME);
= String.format("%s%s%s", Path.DELIMITER, Path.HOME, Path.DELIMITER);

private final Path workdir;

public TildePathExpander(final Path workdir) {
this.workdir = workdir;
}

public Path expand(final Path remote) {
public String expand(final String remote) {
return this.expand(remote, PREFIX);
}

protected Path expand(final Path remote, final String format) {
if(remote.getAbsolute().startsWith(format)) {
return new Path(StringUtils.replaceOnce(remote.getAbsolute(), format, workdir.getAbsolute()),
remote.getType());
/**
* @param remote Path
* @param prefix Prefix to replace in path
* @return Absolute path with prefix replaced with working directory path
*/
public String expand(final String remote, final String prefix) {
if(remote.startsWith(prefix)) {
return StringUtils.replaceOnce(remote, prefix, workdir.getAbsolute() + Path.DELIMITER);
}
return remote;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public Set<ProfileDescription> find(final Visitor visitor) throws BackgroundExce
}
final ProfileFilter filter = new ProfileFilter();
final AttributedList<Path> list = session.getFeature(ListService.class).list(new DelegatingHomeFeature(
new DefaultPathHomeFeature(session.getHost())).find(), new DisabledListProgressListener());
new DefaultPathHomeFeature(session)).find(), new DisabledListProgressListener());
return list.filter(filter).toStream().map(file -> visitor.visit(new RemoteProfileDescription(protocols, file,
new LazyInitializer<Local>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ public class DefaultHomeFinderService implements Home {
private final Home chain;

public DefaultHomeFinderService(final Session<?> session) {
// Chained implementation with precedence workdir > default path > remote default
this.chain = new PathAttributesHomeFeature(session, new DelegatingHomeFeature(new WorkdirHomeFeature(session.getHost()),
new DefaultPathHomeFeature(session.getHost()), session.getFeature(Home.class)), session.getFeature(AttributesFinder.class), session.getFeature(PathContainerService.class));
this.chain = new PathAttributesHomeFeature(session,
// Chained implementation with precedence workdir > default path > remote default
new DelegatingHomeFeature(
new WorkdirHomeFeature(session.getHost()),
new DefaultPathHomeFeature(session),
session.getFeature(Home.class)),
session.getFeature(AttributesFinder.class), session.getFeature(PathContainerService.class));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,44 @@
* feedback@cyberduck.ch
*/

import ch.cyberduck.core.Host;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.PathNormalizer;
import ch.cyberduck.core.Session;
import ch.cyberduck.core.TildePathExpander;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.features.Home;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.EnumSet;

public class DefaultPathHomeFeature extends AbstractHomeFeature {
private static final Logger log = LogManager.getLogger(DefaultPathHomeFeature.class);

private final Host host;
private final Session<?> session;

public DefaultPathHomeFeature(final Host host) {
this.host = host;
public DefaultPathHomeFeature(final Session<?> session) {
this.session = session;
}

@Override
public Path find() throws BackgroundException {
if(StringUtils.isNotBlank(host.getDefaultPath())) {
return PathNormalizer.compose(ROOT, host.getDefaultPath());
if(StringUtils.isNotBlank(session.getHost().getDefaultPath())) {
if(StringUtils.startsWith(session.getHost().getDefaultPath(), Path.HOME)) {
final Home feature = session.getFeature(Home.class);
if(null == feature) {
// No native implementation
}
else {
return new Path(new TildePathExpander(feature.find()).expand(session.getHost().getDefaultPath(), Path.HOME + Path.DELIMITER), EnumSet.of(Path.Type.directory));
}
}
return PathNormalizer.compose(ROOT, session.getHost().getDefaultPath());
}
if(log.isDebugEnabled()) {
log.debug(String.format("No default path set for bookmark %s", host));
log.debug(String.format("No default path set for bookmark %s", session));
}
// No default path configured
return null;
Expand Down
22 changes: 10 additions & 12 deletions core/src/test/java/ch/cyberduck/core/TildePathExpanderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,22 @@
public class TildePathExpanderTest {

@Test
public void testExpand() throws Exception {
final Path expanded = new TildePathExpander(new Path("/home/jenkins", EnumSet.of(Path.Type.directory)))
.expand(new Path("~/f", EnumSet.of(Path.Type.file)));
assertEquals(new Path("/home/jenkins/f", EnumSet.of(Path.Type.file)), expanded);
assertEquals(new Path("/home/jenkins", EnumSet.of(Path.Type.directory)), expanded.getParent());
public void testExpand() {
final String expanded = new TildePathExpander(new Path("/home/jenkins", EnumSet.of(Path.Type.directory)))
.expand("~/f", "~/");
assertEquals("/home/jenkins/f", expanded);
}

@Test
public void testExpandPathWithDirectory() throws Exception {
final Path expanded = new TildePathExpander(new Path("/home/jenkins", EnumSet.of(Path.Type.directory)))
.expand(new Path("/~/f/s", EnumSet.of(Path.Type.file)));
assertEquals(new Path("/home/jenkins/f/s", EnumSet.of(Path.Type.file)), expanded);
assertEquals(new Path("/home/jenkins/f", EnumSet.of(Path.Type.directory)), expanded.getParent());
public void testExpandPathWithDirectory() {
final String expanded = new TildePathExpander(new Path("/home/jenkins", EnumSet.of(Path.Type.directory)))
.expand("/~/f/s");
assertEquals("/home/jenkins/f/s", expanded);
}

@Test
public void testNoExpand() throws Exception {
final Path f = new Path("/f", EnumSet.of(Path.Type.file));
public void testNoExpand() {
final String f = "/f";
assertSame(f, new TildePathExpander(new Path("/home/jenkins", EnumSet.of(Path.Type.directory))).expand(f));
}
}
2 changes: 1 addition & 1 deletion s3/src/main/java/ch/cyberduck/core/s3/S3Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public void login(final Proxy proxy, final LoginCallback prompt, final CancelCal
return;
}
try {
final Path home = new DelegatingHomeFeature(new DefaultPathHomeFeature(host)).find();
final Path home = new DelegatingHomeFeature(new DefaultPathHomeFeature(this)).find();
final Location.Name location = new S3PathStyleFallbackAdapter<>(client, new BackgroundExceptionCallable<Location.Name>() {
@Override
public Location.Name call() throws BackgroundException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package ch.cyberduck.core.shared;

/*
* Copyright (c) 2002-2023 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*/

import ch.cyberduck.core.sftp.AbstractSFTPTest;
import ch.cyberduck.test.IntegrationTest;

import org.junit.Test;
import org.junit.experimental.categories.Category;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

@Category(IntegrationTest.class)
public class DefaultPathHomeFeatureTest extends AbstractSFTPTest {

@Test
public void testFind() throws Exception {
final DefaultPathHomeFeature feature = new DefaultPathHomeFeature(session);
assertNull(feature.find());
session.getHost().setDefaultPath("~/d");
assertEquals("/d", feature.find().getAbsolute());
session.getHost().setDefaultPath("~d");
assertEquals("/~d", feature.find().getAbsolute());
session.getHost().setDefaultPath("/~d");
assertEquals("/~d", feature.find().getAbsolute());
}
}
4 changes: 2 additions & 2 deletions webdav/src/main/java/ch/cyberduck/core/dav/DAVSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public void login(final Proxy proxy, final LoginCallback prompt, final CancelCal
return;
}
try {
final Path home = new DelegatingHomeFeature(new WorkdirHomeFeature(host), new DefaultPathHomeFeature(host)).find();
final Path home = new DelegatingHomeFeature(new WorkdirHomeFeature(host), new DefaultPathHomeFeature(this)).find();
final HttpHead head = new HttpHead(new DAVPathEncoder().encode(home));
try {
client.execute(head, new MicrosoftIISFeaturesResponseHandler());
Expand Down Expand Up @@ -234,7 +234,7 @@ public void chunk(final Path parent, final AttributedList<Path> list) throws Lis
public boolean alert(final ConnectionCallback callback) throws BackgroundException {
if(super.alert(callback)) {
// Propose protocol change if HEAD request redirects to HTTPS
final Path home = new DelegatingHomeFeature(new DefaultPathHomeFeature(host)).find();
final Path home = new DelegatingHomeFeature(new DefaultPathHomeFeature(this)).find();
try {
final RequestConfig context = client.context().getRequestConfig();
final HttpHead request = new HttpHead(new DAVPathEncoder().encode(home));
Expand Down

0 comments on commit f7e5329

Please sign in to comment.