Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update existing repo: #122

Closed

Conversation

tommasobertoni
Copy link

@tommasobertoni tommasobertoni commented Mar 12, 2017

When a user submits a repository that already exists, a page is returned where he can choose if he wants to go to the existing source or force the update.

sourcebrowser_update

Added a new action "Update" (and a View) in the UploadController.
Refactored some of the ProcessSolution logic into the UploadRepository class.
As suggested in the comments (by Amadeus Wieczorek), added support for multi-solution repository and parallel solution processing.

(Also proposed in issue #114)

when a user submits a repository that already exists, a page is returned where he can choose if he wants to go to the existing source or force the update.

Added a new action "Update" (and a View) in the UploadController.
Refactored some of the ProcessSolution logic into the UploadRepository class.
As suggested in the comments (by Amadeus Wieczorek), added support for multi-solution repository and parallel solution processing.
@JoshVarty
Copy link
Contributor

Thanks for the contribution!

It's been a long time since we've done anything here, but I'll try to jog my memory and take a look this weekend.

/cc @AmadeusW

@tommasobertoni
Copy link
Author

Yes, I noticed the repo's inactivity. Thank you for your time.

I'm actually using SourceBrowser for a project of mine, and I came across the inability to update the previous version that I uploaded, so this is the main functionality that I'd like to see in production.

There is one problem with the multi-solution repository support, though: references of types defined in another solution are not recognized during the processing, therefore you're not able to "click" on a type that is defined in another solution.

Let me know if this PR requires some refactoring to be ready to be merged.

@@ -26,7 +26,7 @@ public virtual void Visit(WorkspaceModel workspaceModel)

protected virtual void VisitWorkspace(WorkspaceModel workspaceModel)
{
foreach(var child in _workspaceModel.Children)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird, we're not even using this backing field _workspaceModel.

Copy link
Contributor

@JoshVarty JoshVarty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general this looks like something we'd like to have, thanks again for working on it!

Just a few comments from me, and maybe @AmadeusW will be able to take a look at some point

@@ -34,20 +35,55 @@ public TreeViewTransformer(string savePath, string userName, string repoName)

protected override void VisitWorkspace(WorkspaceModel workspaceModel)
{
using (var stringWriter = new StreamWriter(_savePath, false))
using(_writer = new HtmlTextWriter(stringWriter))
// The first WorkspaceModel that is visited is the root of the tree view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this code had to change. This PR is making it possible to re-analyze solutions so I wouldn't think this would be a required change.

var stagingSolutionPaths = GetSolutionPaths(repoSourceStagingPath);
if (stagingSolutionPaths.Length == 0)
{
throw new NoSolutionsFoundException();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if we didn't introduce a custom exception type. Instead, you could consider returning an enum.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're saying something like this?

public enum ProcessRepoResult
{
    Failed,
    NoSolutionsFound,
    Successful,
}

internal static ProcessRepoResult ProcessRepo(...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, that looks good to me.

_writer.RenderEndTag();
_writer.WriteLine();
_writer.Dispose();
_sw.Dispose();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_sw should be null so that it's created again. But I also don't understand why this change is necessary.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll address here your doubts about the changes in the TreeViewTransformer.VisitWorkspace method:

the changes that I made to make the application able to process multiple solutions in the same repository were to process all the .sln files in parallel and when this processing was finished a new WorkspaceModel item was created and it's children were the WorkspaceModel resulted from the solutions.

When the TreeViewTransformer visited the first WorkspaceModel (which is the root) it created the writers and then it invoked the base method, which recursively visited all the sub nodes.
This means that when the transformer visited the solutions' WorkspaceModels under the root, it created again the writers (because projectItem is a WorkspaceModel), and therefore tried to create the same output file, which lead to an IOException: "The process cannot access the file 'treeView.html' because it is being used by another process."

Anyway, what I wrote was more of a hack than a proper fix, so I'd like to use another approach: by restoring the TreeViewTransformer class as it was before of my changes, we can bypass the same problem by adding all the solutions' children to the root node, instead of the solutions' WorkspaceModels.

So, in the UploadRepository.ProcessRepo method, replace

// Add all the results to the root workspace model.
foreach (var workspace in processedWorkspaces)
    rootWorkspaceModel.Children.Add(workspace);

// WorkspaceModel (root)
// - WorkspaceModel (sln1)
//   - FolderModel
//     - ...
// - WorkspaceModel (sln2)
//   - FolderModel
//     - ...

with

foreach (var children in processedWorkspaces.SelectMany(e => e.Children))
    rootWorkspaceModel.Children.Add(children);

// WorkspaceModel (root)
// - FolderModel (from sln1's WorkspaceModel)
//   - ...
// - FolderModel (from sln2's WorkspaceModel)
//   - ...

resulting in a single WorkspaceModel.

Please, give me your opinions about this. Thanks!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
I tried in implementing the changes that I described above, but in some cases there are problems with repositories with many solutions such that the result is not really good.
Take for example Hangfire: there are two solutions in the root and they share some source files. By flattening the hierarchy in the root WorkplaceModel, the generated treeview is not really readable

sb_hang_old

I tried to solve this by adding the solutions' children to a new FolderModel instead of directly to the root, and indeed the new treeview was better

sb_hang_new

but then the navigation didn't work well because the relative paths didn't match the files in the treeview anymore.

I'm thinking that this could be solved by navigating to a solution's treeview when you click on the solution's name, so basically when you go to /Browse/{user}/{repo} the treeview section shows the available solutions.

But before going this path, I need your opinions.
Thank you

Added lock in SolutionAnalayzer to fix the exception thrown by MSBuildWorkspace.Create() when executed concurrently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants