Why on RemoteFileInfo moving back and forward on the same Session the FullName repeat it self on the FullName value property? - winscp

I have a question that I have no idea how to ask in a simple way so I will do and introduction fist and the question at the end I hope that you get the idea
Using RemoteFileInfo C# class you get the files in the location and two additional records parent directory and current directory.
Searching on “/” I will get:
/.. parent directory
/. Current directory
/Test file folder fullname
/Test2 file folder fullname
If in the same Session I move forward to the Test folder using “/Test” I get:
/TEST/.. parent directory
/TEST/. Current directory
/TEST/New folder file folder full name
/TEST/New folder2 file folder full name
If in the same Session I go back to the previous folder using the parent directory “/TEST/..” I get:
/TEST/./../.. parent directory
/TEST/./../. current directory
/TEST/./../.. file folder full name
/TEST2/./../.. file folder full name
If in the same Session I go forward again to Test Folder using the test folder full name “/TEST/./../TEST” that I get on the previous result I get:
/TEST/./../TEST/.. parent directory
/TEST/./../TEST/. current directory
/TEST/./../TEST/New folder
/TEST/./../TEST/New folder2
If I keep back and forward in the same Session using the parent fullname or the file folder fullname it works it moves to the right location but each time the fullname keep growing with the previous fullname on it. if there a way I can get a single path when moving back and forward? Like when I go to the “/” after moving back and forward I get:
/.. parent directory
/. Current directory
/Test file folder full name
/Test2 file folder full name
I’m doing a single file explorer interface and I want to show the user the current path but is confusing showing something like this /TEST/./../TEST/New folder as current location.
Please let me know if better explanation is need it ;)
I made Minimal Reproducible Example using C# Console Application.
class Program
{
static Session session = new Session();
static void Main(string[] args)
{
var l = new List<DirectoryInformation>();
string GoToThisDirectory = "";
//OPEN SESSION
SessionIni();
//Get File information for the Root folder
Console.WriteLine("ROOT FOLDER");
l = GetDirFiles("/TEST");
foreach (var item in l)
{
// let's take the fist directory that is not this directory to move to that one next time
if (item.IsThisDirectory == false)
{
GoToThisDirectory = item.FullName;
}
//Display the current directory
if (item.IsThisDirectory == true)
{
Console.WriteLine(string.Concat("CURRENT FOLDER: ", item.FullName));
}
Console.WriteLine(string.Concat(" FullName: ", item.FullName,
" IsDirectory: ", item.IsDirectory,
" IsThisDirectory: ", item.IsThisDirectory,
" IsParentDirectory: ", item.IsParentDirectory));
}
Console.WriteLine();
l = GetDirFiles(GoToThisDirectory);
Console.WriteLine("MOVE FORWARD TO LEVEL1 FOLDER");
foreach (var item in l)
{
// let's take the parent directory folder to move to that one next time
if (item.IsParentDirectory == true)
{
GoToThisDirectory = item.FullName;
}
if (item.IsThisDirectory == true)
{
Console.WriteLine(string.Concat("CURRENT FOLDER: ", item.FullName));
}
Console.WriteLine(string.Concat(" FullName: ", item.FullName,
" IsDirectory: ", item.IsDirectory,
" IsThisDirectory: ", item.IsThisDirectory,
" IsParentDirectory: ", item.IsParentDirectory));
}
Console.WriteLine();
l = GetDirFiles(GoToThisDirectory);
Console.WriteLine("MOVE BACK TO PARENT DIRECTORY FOLDER");
foreach (var item in l)
{
// let's take the fist directory that is not this directory to move to that one again
if (item.IsThisDirectory == false)
{
GoToThisDirectory = item.FullName;
}
if (item.IsThisDirectory == true)
{
Console.WriteLine(string.Concat("CURRENT FOLDER: ", item.FullName));
}
Console.WriteLine(string.Concat(" FullName: ", item.FullName,
" IsDirectory: ", item.IsDirectory,
" IsThisDirectory: ", item.IsThisDirectory,
" IsParentDirectory: ", item.IsParentDirectory));
}
Console.WriteLine();
l = GetDirFiles(GoToThisDirectory);
Console.WriteLine("MOVE BACK AGAIN TO LEVEL1 FOLDER");
foreach (var item in l)
{
if (item.IsThisDirectory == true)
{
Console.WriteLine(string.Concat("CURRENT FOLDER: ", item.FullName));
}
Console.WriteLine(string.Concat(" FullName: ", item.FullName,
" IsDirectory: ", item.IsDirectory,
" IsThisDirectory: ", item.IsThisDirectory,
" IsParentDirectory: ", item.IsParentDirectory));
}
Console.Read();
}
private static void SessionIni()
{
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = "XX.XX.XX.XX",
UserName = "UserName",
Password = "Password",
SshHostKeyFingerprint = "XXXXXXXXXXXXXXX",
};
session.Open(sessionOptions);
}
private static List<DirectoryInformation> GetDirFiles(string dir)
{
var l = new List<DirectoryInformation>();
RemoteDirectoryInfo directory = session.ListDirectory(dir);
foreach (RemoteFileInfo fileInfo in directory.Files)
{
l.Add(new DirectoryInformation
{
Name = fileInfo.Name,
FullName = fileInfo.FullName,
IsDirectory = fileInfo.IsDirectory,
IsThisDirectory = fileInfo.IsThisDirectory,
IsParentDirectory = fileInfo.IsParentDirectory,
});
}
return l;
}
}
class DirectoryInformation
{
public string Name { get; set; }
public string FullName { get; set; }
public bool IsDirectory { get; set; }
public bool IsThisDirectory { get; set; }
public bool IsParentDirectory { get; set; }
}
Console Read:
ROOT FOLDER
CURRENT FOLDER: /TEST/.
FullName: /TEST/. IsDirectory: True IsThisDirectory: True IsParentDirectory: False
FullName: /TEST/.. IsDirectory: True IsThisDirectory: False IsParentDirectory: True
FullName: /TEST/Level1 IsDirectory: True IsThisDirectory: False IsParentDirectory: False
MOVE FORWARD TO LEVEL1 FOLDER
CURRENT FOLDER: /TEST/Level1/.
FullName: /TEST/Level1/. IsDirectory: True IsThisDirectory: True IsParentDirectory: False
FullName: /TEST/Level1/.. IsDirectory: True IsThisDirectory: False IsParentDirectory: True
FullName: /TEST/Level1/Level2 IsDirectory: True IsThisDirectory: False IsParentDirectory: False
MOVE BACK TO PARENT DIRECTORY FOLDER
CURRENT FOLDER: /TEST/Level1/../.
FullName: /TEST/Level1/../. IsDirectory: True IsThisDirectory: True IsParentDirectory: False
FullName: /TEST/Level1/../.. IsDirectory: True IsThisDirectory: False IsParentDirectory: True
FullName: /TEST/Level1/../Level1 IsDirectory: True IsThisDirectory: False IsParentDirectory: False
MOVE BACK AGAIN TO LEVEL1 FOLDER
CURRENT FOLDER: /TEST/Level1/../Level1/.
FullName: /TEST/Level1/../Level1/. IsDirectory: True IsThisDirectory: True IsParentDirectory: False
FullName: /TEST/Level1/../Level1/.. IsDirectory: True IsThisDirectory: False IsParentDirectory: True
FullName: /TEST/Level1/../Level1/Level1 IsDirectory: True IsThisDirectory: False IsParentDirectory: False
The last current forlder shows:
CURRENT FOLDER: /TEST/Level1/../Level1/.
and I wish to get
/TEST/Level1/

Do not blindly concatenate the paths.
Process the . and .. in your code.
In general, the . entry should be ignored. It is hardly useful for the end user.
And for the .., instead of trying to access the /base/path/subfolder/.. go up to /base/path.

Related

Kentico 11 - MediaFileInfoProvider.DeleteMediaFileInfo Not Deleting

MediaFileInfo updateFile = MediaFileInfoProvider.GetMediaFileInfo(library.LibraryID, file.Name);
The above line of code is not removing the file from the media library as I expected. This is for a Scheduled Task in Kentico 11 MVC. The new file does get created and is renamed by the System to prevent conflicts.
I would like to delete the existing file before importing the updated version of the file. I would even be satisfied if the new file overwrote the existing file.
public void UpdateMediaFile(MediaLibraryInfo library, string fileName, string importPath)
{
//LumberMarketReport.pdf and PanelMarketReport.pdf
if (library != null)
{
// Prepares a path to a local file
string filePath = fileName;
// Prepares a CMS.IO.FileInfo object representing the local file
CMS.IO.FileInfo file = CMS.IO.FileInfo.New(filePath);
if (file != null)
{
#region "Delete Existing"
MediaFileInfo updateFile = MediaFileInfoProvider.GetMediaFileInfo(library.LibraryID, file.Name);
if (updateFile != null)
{
MediaFileInfoProvider.DeleteMediaFileInfo(updateFile);
}
#endregion
#region "Create File"
// Creates a new media library file object
MediaFileInfo mediaFile = new MediaFileInfo(filePath, library.LibraryID);
// Sets the media library file properties
mediaFile.FileName = file.Name;
mediaFile.FileDescription = "This file was added through the API.";
mediaFile.FilePath = "/"; // Sets the path within the media library's folder structure
mediaFile.FileExtension = file.Extension;
mediaFile.FileMimeType = MimeTypeHelper.GetMimetype(file.Extension);
mediaFile.FileSiteID = SiteContext.CurrentSiteID;
mediaFile.FileLibraryID = library.LibraryID;
mediaFile.FileSize = file.Length;
if (file.Name == "PanelMarketReport.pdf")
{
mediaFile.FileTitle = "Panel Market Report";
mediaFile.SetValue("FileCategoryID", 19);
}
else if (file.Name == "LumberMarketReport.pdf")
{
mediaFile.FileTitle = "Lumber Market Report";
mediaFile.SetValue("FileCategoryID", 57);
}
// Saves the media library file
MediaFileInfoProvider.SetMediaFileInfo(mediaFile);
#endregion
}
}
}
I would add logging to make sure your code is getting hit. Make sure updatefile isn't null. I think you have to pass in the file path in the media library and not just the name.
If I am not mistaken MediaFileInfoProvider.DeleteMediaFileInfo will remove a record from DB but not physically delete the file, so you need to call CMS.IO.FileInfo.Delete(filePath) to delete it from disk.

From DLFileEntry get "/full/path/to/file"

In Liferay's Document and Media, I created a folder called myfolder containing a folder called subfolder containing a file called file.txt.
I have the DLFileEntry of file.txt.
How to get the string /folder/subfolder/file.txt?
Notes:
Context: For display/reporting purposes, I need to get the full path of the file, a bit like how it would appear in a breadcrumb.
getTreePath() gives identifiers such as /32701/ instead of folder names
I greped the whole Liferay 7 DXP SP4 for getBreadcrumbs and no source code came, even though a method with this name seemed to exist in Liferay 5.
Here is my implementation:
protected String fullPath(DLFileEntry file) throws PortalException {
String fileName = file.getFileName();
DLFolder folder = file.getFolder();
if (folder == null) {
return "/" + fileName;
}
else {
return fullPath(folder) + "/" + fileName;
}
}
protected String fullPath(DLFolder folder) throws PortalException {
String folderName = folder.getName();
DLFolder parent = folder.getParentFolder();
if (parent == null) {
return "/" + folderName;
}
else {
return fullPath(parent) + folderName;
}
}
All ideas to improve maintainability and performance are welcome!

Gradle: Force Custom Task to always run (no cache)

I wrote up a custom Gradle task to handle some dependency resolution on the file system where the paths are configurable. I want tasks of this type to always run. It seems though they only run once, I'm guessing because the inputs never seem to change.
I am aware of using configurations { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } to effectively disable the cache, but I only want it to apply to very specific tasks. Also am aware of --rerun-tasks command line prompt, which is also similar. Neither feel like the best solution, there must be a way to set this up properly in the custom task definition.
Follows is my current implementation. I also had a version prior where the first 3 def String statements were instead #Input annotated String declarations.
class ResolveProjectArchiveDependency extends DefaultTask {
def String archiveFilename = ""
def String relativeArchivePath = ""
def String dependencyScope = ""
#OutputFile
File outputFile
#TaskAction
void resolveArtifact() {
def arcFile = project.file("dependencies/"+dependencyScope+"/"+archiveFilename)
def newArcFile = ""
if(project.hasProperty('environmentSeparated') && project.hasProperty('separatedDependencyRoot')){
println "Properties set denoting the prerelease environment is separated"
newArcFile = project.file(project.ext.separatedDependencyRoot+relativeArchivePath+archiveFilename)
} else {
newArcFile = project.file('../../'+relativeArchivePath+archiveFilename)
}
if(!newArcFile.isFile()){
println "Warn: Could not find the latest copy of " + archiveFilename + ".."
if(!arcFile.isFile()) {
println "Error: No version of " + archiveFilename + " can be found"
throw new StopExecutionException(archiveFilename +" missing")
}
}
if(!arcFile.isFile()) {
println archiveFilename + " jar not in dependencies, pulling from archives"
} else {
println archiveFilename + " jar in dependencies. Checking for staleness"
def oldHash = generateMD5(new File(arcFile.path))
def newHash = generateMD5(new File(newArcFile.path))
if(newHash.equals(oldHash)) {
println "Hashes for the jars match. Not pulling in a copy"
return
}
}
//Copy the archive
project.copy {
println "Copying " + archiveFilename
from newArcFile
into "dependencies/"+dependencyScope
}
}
def generateMD5(final file) {
MessageDigest digest = MessageDigest.getInstance("MD5")
file.withInputStream(){is->
byte[] buffer = new byte[8192]
int read = 0
while( (read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
}
byte[] md5sum = digest.digest()
BigInteger bigInt = new BigInteger(1, md5sum)
return bigInt.toString(16)
}
}
Here's an example of usage of the task:
task handleManagementArchive (type: com.moremagic.ResolveProjectArchiveDependency) {
archiveFilename = 'management.jar'
relativeArchivePath = 'management/dist/'
dependencyScope = 'compile/archive'
outputFile = file('dependencies/'+dependencyScope+'/'+archiveFilename)
}
You can achieve this by setting outputs.upToDateWhen { false } on the task.
This can be performed in your build.gradle file:
handleManagementArchive.outputs.upToDateWhen { false }
It can also be done in the constructor of your custom task.
ResolveProjectArchiveDependency() {
outputs.upToDateWhen { false }
}

How to know the branch of a tag using SVNKit java API?

Can someone please tell me how to figure out branch of an svn tag? Would be great if there is any working code, that gets me branches for certain tags? Thanks.
I use this command line command as of now to see it on console
svn log -v -l 2 "path to tag"
Resolved.
ISVNLogEntryHandler handler = new ISVNLogEntryHandler() {
#Override
public void handleLogEntry(SVNLogEntry arg0) throws SVNException {
Map<String, SVNLogEntryPath> map = arg0.getChangedPaths();
for (Map.Entry<String, SVNLogEntryPath> entry: map.entrySet()) {
SVNLogEntryPath svnLogEntryPath = entry.getValue();
System.out.println(Calendar.getInstance().getTime());
System.out.println("Path : " + svnLogEntryPath.getPath());
System.out.println("Kind : " + svnLogEntryPath.getKind());
System.out.println("Type : " + svnLogEntryPath.getType());
System.out.println("Copy Path : " + svnLogEntryPath.getCopyPath()); // gives the tag's branch
System.out.println("Branch : " + svnLogEntryPath.getCopyPath().substring(svnLogEntryPath.getCopyPath().lastIndexOf('/')+1)); // gives the tag's branch
System.out.println("Copy Revision : " + svnLogEntryPath.getCopyRevision());
System.out.println("------------------------");
}
}
};
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(userName, password);
boolean readonly = true;
ISVNOptions options = SVNWCUtil.createDefaultOptions(readonly);
// Get log client
SVNLogClient logClient = new SVNLogClient(authManager, options);
String[] paths = { pathToTag};
logClient.doLog(svnurl, paths, SVNRevision.HEAD, startRevision, SVNRevision.HEAD, true, true, 2, handler);

Domain object string list - Adding on the fly

Maybe this is an issue with persistance and the domain object. So I have a list of manual notes that can be added to a person. My person class looks similar to this (I've wrapped the object in transients to ignore persistence):
class Person {
...
List<String> notes = new ArrayList<String>()
...
}
When I update a person with a note (textfield on view will allow note to be added), I want to do something simple like adding the new note to the array list tied to the person:
class PersonController {
...
def update() {
def contactInstance = Contact.get(params.id)
if (!contactInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'contact.label', default: 'Contact'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (contactInstance.version > version) {
contactInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'contact.label', default: 'Contact')] as Object[],
"Another user has updated this Contact while you were editing")
render(view: "edit", model: [contactInstance: contactInstance])
return
}
}
contactInstance.properties = params
/**
* Check for inactive - Then flag with user and date tag
*/
if(params.isActive == null) {
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
Date date = new Date();
contactInstance.properties.isActiveNote = "Made inactive by " + session.user + " on " + dateFormat.format(date) + "."
}
/**
* Date stamp of the note itself
*/
if(params.notes.equals("")) {}
else {
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
Date date = new Date();
//contactInstance.properties.notes = contactInstance.properties.notes + " " + params.notes + " - (" + dateFormat.format(date) + " " + session.user + ");"
contactInstance.allThese.add(contactInstance.properties.notes)
println(contactInstance.allThese)
}
if (!contactInstance.save(flush: true)) {
render(view: "edit", model: [contactInstance: contactInstance])
return
}
flash.message = message(code: 'default.updated.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "show", id: contactInstance.id)
}
...
}
The call to update from my gsp:
<g:actionSubmit class="save" action="update" value="${message(code:'default.button.update.label', default: 'Update')}" />
But it just seems to store the array with a single note. Is there a persistance issue with Grails domain objects and collections? It could very well be a simple issue on my end!
Thanks for all the help.
If your view includes multiple <input> fields or <textarea>s with the same name ("notes", to match the field name in your Domain class), Grails will automatically bind the values to your notes array.
You might also look into the new params.list() method that would allow you to iterate through request parameters and then add them individually to your array.

Resources