exercism / problem-specifications

Shared metadata for exercism exercises.
MIT License
326 stars 541 forks source link

Is there a way to set a folder's contents to be included in each problem? #601

Open masters3d opened 7 years ago

masters3d commented 7 years ago

I am working on a new track but each exercise its going to have at least 2 duplicated files which I rather have somewhere else for easier updating.

bobExample.ts
bob.test.ts
package.json // Same in every problem 
tsconfig.json // Same in every problem
tslint.json // Same in every problem

Is there a way to have a folder which contents always gets included in each exercise?

petertseng commented 7 years ago

Ah, you know, at Haskell we would greatly enjoy if symlinks were to work. We have a file stack.yaml which is the same in every single exercise. We want to have it only once, instead of duplicated 76 times (once per exercise).

They would work if not for https://github.com/exercism/trackler/issues/13

And in general, I will advise to use symlinks for this purpose:

masters3d commented 7 years ago

symlinks sounds like the perfect solution.

petertseng commented 7 years ago

I wanted to see who else might benefit. The list is last updated on 2017-04-24, trackler version 2.1.0.0.

c

cpp

csharp

ecmascript

elm

erlang

fsharp

haskell

haxe

java

kotlin

lfe

ocaml

powershell

ruby

rust

scala

swift

typescript

stkent commented 7 years ago

Ideally all Java exercises will eventually have the same base build.gradle file. If we really need customization, we could apply from: an optional extension Gradle file on a per-exercise basis. Sort of like a template method for builds!

NobbZ commented 7 years ago

31 exercises all have the same rebar.conf

Which is a mistake that I have to address, they should differ in at least one line.

NobbZ commented 7 years ago

Okay... It was necessary to make them identical in that process. So yes I would be glad if sim linking would work out of the box.

NobbZ commented 7 years ago

Since I had to reboot... How would contributors using Windows be able to create a simlink when they want to add an exercise?

masters3d commented 7 years ago

I don't use Windows so I don't know how realiable sym links are in windows.

masters3d commented 7 years ago

How about just implementing a quick script to copy files from a common directory?

// Makefile

all: replacePackageFileFromCommonToSubFolders

copyPackageFilesToSubFolder:
    @cp -a /common/. exercises/$(ASSIGNMENT)/

replacePackageFileFromCommonToSubFolders:
    @for assignment in $(ASSIGNMENTS); do ASSIGNMENT=$$assignment $(MAKE) copyPackageFilesToSubFolder || exit 1; done
petertseng commented 7 years ago

Well, sure. In that case, since no coordination is required cross-track (we don't need trackler+RubyGems to ensure that symlinks work, nor do we need to agree on a global directory), then each track can handle their own scripting. Then we do not particularly need to discuss anything other than best practices for doing that. For what it's worth, maybe I'll use a shell script.

masters3d commented 7 years ago

@petertseng I was thinking for the tracker just to copy the files from a directory like common instead of trying to get symlinks to work which seems a little more involved and perhaps not portable

petertseng commented 7 years ago

I was thinking for the tracker just to copy the files from a directory like common

So if trackler does it when serving the files to the student on exercism fetch - what will we do for the people who wish to check out the repository locally? Will they have to copy the files through some other means?

masters3d commented 7 years ago

This is a good point. I don't have a good solution. My issue with Typescript track is that I don't have a way to import the example with out breaking the test file. In Swift I don't worry about it because it's a package base system so the file doesn't matter just the type. In Objc I can use a macro but not in JS or Typescript.

#if __has_include("AcronymExample.h")
# import "AcronymExample.h"
# else
# import "Acronym.h"
#endif
petertseng commented 7 years ago

I don't understand why I deleted my code to check for common files; that forced me to rewrite it. Better save it here so that I don't lose it again...

trackler = File.dirname(File.dirname(`gem which trackler`.chomp))

Dir.glob(File.join(trackler, 'tracks', ?*)).sort.each { |track_dir|
  track = File.basename(track_dir)

  # Hash[String(file) => Hash[String(sum) => List[String(exercise)]]]
  files = Hash.new { |h, k| h[k] = Hash.new { |hh, kk| hh[kk] = [] } }

  exercises_dir = File.join(track_dir, 'exercises')
  n_exercises = Dir.glob(File.join(exercises_dir, ?*, '')).size

  `find #{exercises_dir} -type f -exec md5sum {} \\;`.each_line { |l|
    sum, path = l.split
    # Add 1 to remove another slash.
    exercise, file = path[(exercises_dir.size + 1)..-1].split(File::SEPARATOR, 2)
    files[file][sum] << exercise
  }

  track_header = nil

  files.each { |file, variants|
    variants.each { |sum, exercises|
      next if exercises.size < 2
      track_header ||= (puts "# #{track}"; puts; true)
      puts "* **#{exercises.size}/#{n_exercises}** exercises all have the same **#{file}**"
    }
  }
  puts if track_header
}

Related to this issue: the Haskell track has given up on using symlinks given unreliable packaging and unknown support on all platforms.

Insti commented 7 years ago

Being able to use symlinks would be nice, but Rubygems does not properly support them.

Trackler will serve the files that are present in the track repository.

Tracks should be responsible for copying files from a common location to the individual exercise directories.

masters3d commented 7 years ago

Tracks are not responsible to copy documentation manually. Why should we litter the commit history with duplicate files for packages? We do no need symlinks.

Insti commented 7 years ago

@masters3d, I'm not sure what your last comment means.

I think your initial request https://github.com/exercism/x-common/issues/601#issue-208233571 is reasonable.

Symlinks would be one way to do this but we have concluded that this will not currently work.

@petertseng made a good point about needing the files to be present in the git repository https://github.com/exercism/x-common/issues/601#issuecomment-281204731

I cannot think of a solution that does not involve copying files and this can easily be done by a script local to the track repository that copies.

I'm not aware of any limitations on commit history size that this policy would affect, and in any case could be only 1 commit that updated all the files that needed updating.

If someone can come up with some other workable solution I will be happy to help implement it.

petertseng commented 5 years ago

Recall that symlinks were proposed as a solution to this issue.

Further, recall that a previous reason why symlinks did not work was because of https://github.com/exercism/trackler/issues/13

Finally, note that trackler is no longer in use, therefore the above is not a blocker for symlinks.

Therefore, it is now once again possible to test whether symlinks work.

You should use caution when testing this, because https://github.com/exercism/exercism/issues/4219 means that the version any given student fetches is permanent. Consider testing this only with expendable tracks and/or exercises. (The preceding paragraph is no longer true and thus has now been struck out: See https://github.com/exercism/website/pull/464)

Note that although the above trackler-related symlink blocker is no longer present, the other considerations with symlinks remain (the main question being whether they will cause problems for any contributors on platforms that do not support symlinks)