Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #4419 from zaggino/duplicate_filenames
Browse files Browse the repository at this point in the history
Adds directory names to the files in working tree, ...
  • Loading branch information
TomMalbran committed Aug 6, 2013
2 parents 766eb36 + da50ad0 commit 0e7e0f5
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 10 deletions.
104 changes: 104 additions & 0 deletions src/project/WorkingSetView.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ define(function (require, exports, module) {
Commands = require("command/Commands"),
Menus = require("command/Menus"),
FileViewController = require("project/FileViewController"),
CollectionUtils = require("utils/CollectionUtils"),
ViewUtils = require("utils/ViewUtils");


Expand Down Expand Up @@ -88,6 +89,108 @@ define(function (require, exports, module) {
}
}

/**
* @private
* Adds directory names to elements representing passed files in working tree
* @param {Array.<FileEntry>} filesList - list of FileEntries with the same filename
*/
function _addDirectoryNamesToWorkingTreeFiles(filesList) {
// filesList must have at least two files in it for this to make sense
if (filesList.length <= 1) {
return;
}

// First collect paths from the list of files and fill map with them
var map = {}, filePaths = [], displayPaths = [];
filesList.forEach(function (file, index) {
var fp = file.fullPath.split("/");
fp.pop(); // Remove the filename itself
displayPaths[index] = fp.pop();
filePaths[index] = fp;

if (!map[displayPaths[index]]) {
map[displayPaths[index]] = [index];
} else {
map[displayPaths[index]].push(index);
}
});

// This function is used to loop through map and resolve duplicate names
var processMap = function (map) {
var didSomething = false;
CollectionUtils.forEach(map, function (arr, key) {
// length > 1 means we have duplicates that need to be resolved
if (arr.length > 1) {
arr.forEach(function (index) {
if (filePaths[index].length !== 0) {
displayPaths[index] = filePaths[index].pop() + "/" + displayPaths[index];
didSomething = true;

if (!map[displayPaths[index]]) {
map[displayPaths[index]] = [index];
} else {
map[displayPaths[index]].push(index);
}
}
});
}
delete map[key];
});
return didSomething;
};

var repeat;
do {
repeat = processMap(map);
} while (repeat);

// Go through open files and add directories to appropriate entries
$openFilesContainer.find("ul > li").each(function () {
var $li = $(this);
var io = filesList.indexOf($li.data(_FILE_KEY));
if (io !== -1) {
var dirSplit = displayPaths[io].split("/");
if (dirSplit.length > 3) {
displayPaths[io] = dirSplit[0] + "/\u2026/" + dirSplit[dirSplit.length - 1];
}

var $dir = $("<span class='directory'/>").html(" &mdash; " + displayPaths[io]);
$li.children("a").append($dir);
}
});
}

/**
* @private
* Looks for files with the same name in the working set
* and adds a parent directory name to them
*/
function _checkForDuplicatesInWorkingTree() {
var map = {},
fileList = DocumentManager.getWorkingSet();

// We need to always clear current directories as files could be removed from working tree.
$openFilesContainer.find("ul > li > a > span.directory").remove();

// Go through files and fill map with arrays of files.
fileList.forEach(function (file) {
// Use the same function that is used to create html for file.
var displayHtml = ViewUtils.getFileEntryDisplay(file);

if (!map[displayHtml]) {
map[displayHtml] = [];
}
map[displayHtml].push(file);
});

// Go through the map and solve the arrays with length over 1. Ignore the rest.
CollectionUtils.forEach(map, function (value) {
if (value.length > 1) {
_addDirectoryNamesToWorkingTreeFiles(value);
}
});
}

/**
* @private
* Shows/Hides open files list based on working set content.
Expand All @@ -99,6 +202,7 @@ define(function (require, exports, module) {
} else {
$openFilesContainer.show();
$workingSetHeader.show();
_checkForDuplicatesInWorkingTree();
}
_adjustForScrollbars();
_fireSelectionChanged();
Expand Down
6 changes: 5 additions & 1 deletion src/styles/brackets.less
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,13 @@ a, img {
padding: 3px (@sidebar-triangle-size * 2) 3px 0;

cursor: default;

.directory {
font-size: 11px;
}
}

.extension {
.extension, .directory {
color: @project-panel-text-2;
}
}
Expand Down
Empty file.
Empty file.
75 changes: 66 additions & 9 deletions test/spec/WorkingSetView-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global $, define, describe, it, expect, beforeEach, afterEach, waitsFor, runs, beforeFirst, afterLast */
/*global $, define, describe, it, expect, beforeEach, afterEach, waitsFor, waitsForDone, runs, beforeFirst, afterLast */

define(function (require, exports, module) {
"use strict";
Expand All @@ -43,7 +43,6 @@ define(function (require, exports, module) {
testWindow,
workingSetCount;


function openAndMakeDirty(path) {
var doc, didOpen = false, gotError = false;

Expand Down Expand Up @@ -95,7 +94,6 @@ define(function (require, exports, module) {
SpecRunnerUtils.closeTestWindow();
}


beforeFirst(function () {
createTestWindow(this, true);
});
Expand All @@ -116,8 +114,6 @@ define(function (require, exports, module) {
testWindow.closeAllFiles();
});



it("should add a list item when a file is dirtied", function () {
// check if files are added to work set and dirty icons are present
runs(function () {
Expand Down Expand Up @@ -151,7 +147,7 @@ define(function (require, exports, module) {
runs(function () {
var $ = testWindow.$;
var secondItem = $($("#open-files-container > ul").children()[1]);
secondItem.trigger('click');
secondItem.trigger("click");

var $listItems = $("#open-files-container > ul").children();
expect($($listItems[0]).hasClass("selected")).not.toBeTruthy();
Expand Down Expand Up @@ -219,7 +215,7 @@ define(function (require, exports, module) {

// hover over and click on close icon of 2nd list item
var secondItem = $($("#open-files-container > ul").children()[1]);
secondItem.trigger('mouseover');
secondItem.trigger("mouseover");
var closeIcon = secondItem.find(".file-status-icon");
expect(closeIcon.length).toBe(1);

Expand All @@ -228,7 +224,7 @@ define(function (require, exports, module) {
didClose = true;
});

closeIcon.trigger('mousedown');
closeIcon.trigger("mousedown");
});

waitsFor(function () { return didClose; }, "click on working set close icon timeout", 1000);
Expand Down Expand Up @@ -257,7 +253,7 @@ define(function (require, exports, module) {
var $ = testWindow.$;
var secondItem = $("#open-files-container > ul").children().eq(1);
var fileName = secondItem.text();
secondItem.trigger('click');
secondItem.trigger("click");

// Calling FILE_RENAME synchronously works fine here since the item is already visible in project file tree.
// However, if the selected item is not already visible in the tree, this command will complete asynchronously.
Expand All @@ -269,6 +265,67 @@ define(function (require, exports, module) {
expect($projectFileItems.find("a.jstree-clicked").eq(0).siblings("input").eq(0).val()).toBe(fileName);
});
});

it("should show a directory name next to the file name when two files with same names are opened", function () {
runs(function () {
// Count currently opened files
var workingSetCountBeforeTest = workingSetCount;

// First we need to open another file
openAndMakeDirty(testPath + "/directory/file_one.js");

// Wait for file to be added to the working set
waitsFor(function () { return workingSetCount === workingSetCountBeforeTest + 1; }, 1000);

runs(function () {
// Two files with the same name file_one.js should be now opened
var $list = testWindow.$("#open-files-container > ul");
expect($list.find(".directory").length).toBe(2);

// Now close last opened file to hide the directories again
DocumentManager.getCurrentDocument()._markClean(); // so we can close without a save dialog
var didClose = false, gotError = false;
waitsForDone(CommandManager.execute(Commands.FILE_CLOSE), "timeout on FILE_CLOSE", 1000);

// there should be no more directories shown
runs(function () {
expect($list.find(".directory").length).toBe(0);
});
});
});
});

it("should show different directory names, when two files of the same name are opened, located in folders with same name", function () {
runs(function () {
// Count currently opened files
var workingSetCountBeforeTest = workingSetCount;

// Open both files
openAndMakeDirty(testPath + "/directory/file_one.js");
openAndMakeDirty(testPath + "/directory/directory/file_one.js");

// Wait for them to load
waitsFor(function () { return workingSetCount === workingSetCountBeforeTest + 2; }, 1000);

runs(function () {
// Collect all directory names displayed
var $list = testWindow.$("#open-files-container > ul");
var names = $list.find(".directory").map(function () {
return $(this).text();
}).toArray();

// All directory names should be unique
var uniq = 0, map = {};
names.forEach(function (name) {
if (!map[name]) {
map[name] = true;
uniq++;
}
});
expect(uniq).toBe(names.length);
});
});
});

});
});

0 comments on commit 0e7e0f5

Please sign in to comment.