Building a Unix-shell in Rust - Part 3
This is the third post in a series on writing a simple shell in the Rust language. (I suggest you start from the beginning!)
In the previous post , I implemented a simple REPL that simply prints out debug output with the input split by whitespace.
In this post, I would like to take the opportunity to set up tests before much more complex functionality gets included. Consider this to be the first part of what potentially might be multiple posts about writing and organizing testing with cargo
.
Is testing important?🔗
Program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absence. Edsger W. Dijkstra
I don’t think it is controversial to say I think it is important. Good tests can help protect you from accidental regressions in functionality, and can be an added check on your assumptions, and manual testing. My intention is to write objective unit tests that will replace what I've been doing manually.
Why write the tests now? Why not later?🔗
To be honest, I want the tests now because I’m looking for ways to use Rust for production code at work, and I need to get a feel for how a Rust codebase matures. As I am exploring Rust, I have come to be impressed with how easy cargo test
makes it to write and execute tests.
It also will be less work to write test code for a small amount of code I just wrote now, rather than a larger amount of code later. Since it's been my experience that testing will just become reactive. And I get to go back to writing new feature code sooner.
Getting started with unit testing🔗
Testing is something that I always seem to go through with print statements, which is better than nothing, but not the most reliable way to be mindful of functionality regression. I would like to try to write more tests, as well as more functional code.
https://doc.rust-lang.org/book/testing.html
According to the official Rust handbook, for unit-style tests, like the what I would like to write, the convention is to create a tests
module.
I’ll cover integration tests in a later post, when I reorganize the project into different files. For now, I’m going to start slow and try to understand the new parts of Rust I get to use.
In the same file as the rest of my code, I add my test module with unit tests. I’m going to cover testing the tokenize_command()
function.
main.rs
#[cfg(test)]
mod unittest_tokenize_command {
use super::*;
#[test]
#[ignore]
fn empty_command() {
assert_eq!("", tokenize_command("".to_string()).keyword)
}
#[test]
fn test_keyword() {
assert_eq!("test", tokenize_command("test".to_string()).keyword)
}
#[test]
fn no_arg() {
assert_eq!(0, tokenize_command("test".to_string()).args.len())
}
#[test]
fn one_arg() {
assert_eq!(1, tokenize_command("test one".to_string()).args.len())
}
#[test]
fn multi_args() {
assert_eq!(3, tokenize_command("test one two three".to_string()).args.len())
}
#[test]
#[ignore]
fn quotes() {
assert_eq!(2, tokenize_command("test \”one two\” three".to_string()).args.len())
}
}
Breakdown of test module🔗
I’ll introduce the new syntax.
use super::*🔗
The use of use
is new to me in Rust. I assume it means I am bringing in the namespace scope from outside to the top-level (instead of using super::
at every function call)
Since the test module is an inner module, we need to bring the functions from the outside scope into the module’s local scope. We can do this individually, but we can just use *
to pull them all in, even though I’m not going to be testing them all right now.
For more information about this usage, look at the Crates and Modules page in the Rust documentation.
Attributes🔗
The #
lines are called attributes. Attributes are defined by the compiler, and are used for different things. As of Rust 1.17, we currently we cannot create our own attributes. I’ll quickly describe the attributes we use, (but here’s the reference to all of the attributes.
#[test]🔗
The #[test]
attribute labels the functions as tests to the rust compiler. This is how cargo test
knows what functions to run for tests.
#[ignore]🔗
The #[ignore]
attribute tells cargo to skip the test. (However, you can tell cargo to run the ignored tests by running cargo test -- --ignored
) I am using this attribute, because as I started writing tests, I realized I hadn’t covered the functionality that would let the tests pass. I don’t want to forget to do this, so I’ll write the test now.
#[cfg(test)]🔗
In #[cfg(test)]
, we’re using the cfg
attribute on the unittest_tokenize_command
module. In our usage, the attribute tells the Rust compiler to compile the module only when we are compiling tests, like when we run cargo test
.
Running the tests🔗
We just need to run cargo test
.
$ cargo test
Compiling rust-shell v0.1.0 (file:///Users/telant/src/rust-shell)
Finished debug [unoptimized + debuginfo] target(s) in 0.45 secs
Running target/debug/deps/rust_shell-cdb27ec22ae15a63
running 6 tests
test unittest_tokenize_command::empty_command ... ignored
test unittest_tokenize_command::quotes ... ignored
test unittest_tokenize_command::no_arg ... ok
test unittest_tokenize_command::multi_args ... ok
test unittest_tokenize_command::test_keyword ... ok
test unittest_tokenize_command::one_arg ... ok
test result: ok. 4 passed; 0 failed; 2 ignored; 0 measured
And we see that the all but our ignored tests pass, which is good enough for now!
In the next post, I’ll be covering evaluating built-in keywords.


To delete part of a sound file
- Move the slider to the place in the file that you want to cut.
- On the Edit menu, click Delete Before Current Position or Delete After Current Position.
Note
- Until you save the file, you can undo a deletion by clicking the File menu, and then clicking Revert.


I build solutions. Currently I'm helping idealo Internet GmbH to build the best customer experience for online payments.
Contact me
See what I'm currently doing at work. Connect with me, let's get in touch.
Personal stuff. Not much going on there. Millenial, you know.
I'm lurking and commenting as @WolffRob
Mixing music helps me relax. I'm dropping sets every now and then. You can listen to them on Mixcloud.
My other relaxation project: gaming. Once in a while, I record and upload gaming guides for casual players.
Images. Of kittens and puppies. Actually: no. Mostly weird things I come accross.


I am PhD in Computer Sciences and Postdoctoral fellow in the University of Milano Bicocca. I am interested in all sorts of NLP applications. I worked on projects related to recommender systems, information extraction, information retrival and explainability of text classifiers.
Teaching UML, Scrum
Teaching JAVA, ERP
Building Content-Based Filtering approaches for scientific paper recommendation that relies on topic modelling. The profiles of researchers are modelled by a set of topics obtained by applying LDA to the papers written by the researchers. The profile built by this model is easily interpretable, and can explain the recommendation results. Building Collaborative filtering scientific paper recommendation approach which combines content analysis based on LDA, Social Networks (SN) techniques for neighbourhood generation, and the relevance based language model to CF recommendation. We adapted information retrieval techniques in this thesis to the recommendation task and we obtained SOTA results based on the DBLP dataset. Click here. If you want to see a part of the code and the publication.
Building an SVM classifier to extract biological events, biological named entities by using syntactic and semantic features (Java implementation with incorporation of NLP libraries for POS tagging, syntactic parsing and biological named entities recognition), the process includes 2 pipelines: trigger detection which consists of extracting verbs or nouns referring to the biological event and relation detection which extracts the relation between biological named entities and the event trigger.
I am a bookworm (You can follow my readings in my Goodreads account.), travel lover (+10 visited countries) and a movie buff.


THE WAR ZONE A film review by Steve Rhodes Copyright 1999 Steve Rhodes RATING (0 TO ****): *** 1/2
Secrets -- every family has them, but some families' secrets are more shocking than others.
In the directorial debut of Tim Roth, an actor famous for such villainous roles as his Oscar nominated performance in ROB ROY, Roth tackles one of the toughest subjects possible, incest. The astonishing film, THE WAR ZONE, isn't as unwatchable as the title or the early buzz about the picture might suggest. With his almost reverential respect for his actors, Roth lets us share the inner strengths as well as the pain of the teen victims.
Alexander Stuart's sparse script, based on his novel, lets Roth tell the story through a set of incredibly strong visuals. The best actors can do more with their faces than their words, and Roth takes this ensemble cast to new heights of telling imagery. Speaking would just distract from many of the moments anyway. One look at the faces attempting bravely to hold back the tears and the explosive anger, and you know all you need to know.
To an outside observer or even a close neighbor, the patriarchal family in the movie would appear perfectly normal and happy. The gregarious and polite Dad (Ray Winstone) seems kind and gentle and the Mum (Tilda Swinton) just as sweet. Their children, 18-year-old Jessie (Lara Belmont) and 15-year-old Tom (Freddie Cunliffe), might appear a bit withdrawn but nothing more. There's even a new baby girl, which would appear to provide extra joy to their household. As the story unfolds and Tom learns the truth about his father and Jessie, the family dynamics change considerably.
In the movie's most telling scene, Tom finally gets just the evidence he needs, but it so sickens him that he immediately destroys it.
Roth isn't skittish about detailing the incest. The scenes are explicit, not to shock or to titillate but to make clear exactly what is happening and exactly how painful it is. Jessie, who spends most of the time with borderline tears, breaks out into profuse tears during the sex. Roth's approach thus strips away any hint of sensuality, exposing the raw abusive actions of the father. Roth said that he feels the material demands this level of frankness.
The normally picturesque northern coast of Devon in England, where the story is set, is shown at its bleakest. Filmed by Seamus McGarvey with a somber blue-gray palate, the land is pounded by rain and beaten by wind. With hauntingly sad piano music by Simon Boswell, the picture literally cries out to us in anguish.
THE WAR ZONE has but one counterpart, Ang Lee's THE ICE STORM. Both cut through the false exteriors to show us the inner workings of dysfunctional families. Neither is easy viewing, perhaps, but both are emotionally rewarding.
THE WAR ZONE runs 1:39. It is not rated but would probably be NC-17 for explicit sex, nudity, language and some violence. The film would not be appropriate for those under 18.
Email<EMAIL_ADDRESS>Web: http://www.InternetReviews.com
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


 Your goal is to explore the galaxy, mine asteroids for resources, and build new parts onto your ship. (Gameplay: Mine ore, scan for systems, travel to new systems; keep your energy up.)
Power may be sparse at first, but luckily your ship comes equipped with a handy, manual crank for generating energy.
Created in 48 hours for Ludum Dare 39, with the theme of "Running out of power".


{% extends "todos/layouts.html" %} {% block body %}
Webpy is an Todo app that was made in Python (Django Framework). Please feel free to use this and fork this project.
| Task name | Status |
|---|---|
| {{ list.title }} | {% if list.status == 1 %}Fresh | {% endif %}
Glad you are interested in this DIY app.
Todo app with following fields


--- title: January 2018 ---
As a young and relatively small alumni association, every single contribution received is an enormous help and tremendous push forward toward the ambitious goals that we set forth.
We would like to honor and recognize alumni who made sizable contributions to the Alumni Association in 2017. The following individuals will have an Alumni Brick created in their behalf, which will be placed in front of the IRC on the infamous Alumni Brick Path. These individuals have made a contribution of more than 500 EUR to the Association and will have their legacy cemented on campus.
Stephan Huerholz
Max Lohmann
Sara Heidecke
Stefan Rustler
Fabian Russmann
Sami Kerim Galal
Ewa A. Treitz
Benedikt Blomeyer
Elena Isac
The following individuals have shown us through their pledge as Patron Members of the Jacobs Alumni Association, that they are continually fully committed to the ongoing development of this organization. We would like to thank each and every Patron Member for supporting us and for helping us realize our goals.
Klaus Boehnke
Peter Dabrowski
Sami Kerim Galal
Henrike Klavert
Kai Kohlhoff
Benjamin Liebald
Konstantin Mihov
Martin Noack
Cornelia Scheitz
Natalie Schnelle
Raymond Wells
Elizabeth Zeller
Alexander Ziegler-Jöns
Alumni, with your support- be it monetary, time support, expertise- we can achieve anything. The year 2017 was a record-breaking year in our history as an alumni association. We had the largest Homecoming in JU history, we awarded the Alumni Scholarship to another brilliant student in need, with our help JU achieved the largest and most alumni-integrated Career Fair, the Alumni Mentoring Program was relaunched, the new Alumni Database was launched—all of these wonderful accomplishments and more were achieved this year thanks to our great network!


Singsing:
Glad to hear it! I think you'll make us both rich men at this rate. Go and hunt
Pachycephalosaurus and wild striders
and bring back their
bones
.


SimpleText SimpleText under the German version of Mac OS 8 SimpleText under the German version of Mac OS 8 Developer(s) Apple Computer, now Apple Inc. Stable release 1.4 Operating system System 7 – Mac OS 9 Type Text editor License Proprietary SimpleText is the native text editor for the Apple classic Mac OS.[1] SimpleText allows editing including text formatting (underline, italic, bold, etc.), fonts, and sizes. It was developed to integrate the features included in the different versions of TeachText that were created by various software development groups within Apple.[2] It can be considered similar to Windows' WordPad application. In later versions it also gained additional read only display capabilities for PICT files, as well as other Mac OS built-in formats like Quickdraw GX and QTIF, 3DMF and even QuickTime movies.[2] SimpleText can even record short sound samples and, using Apple's PlainTalk speech system, read out text in English. Users who wanted to add sounds longer than 24 seconds, however, needed to use a separate program to create the sound and then paste the desired sound into the document using ResEdit.[2] SimpleText superseded TeachText, which was included in System Software up until Mac OS 8. The need for SimpleText arose after Apple stopped bundling MacWrite, to ensure that every user could open and read Readme documents. The key improvement of SimpleText over TeachText was the addition of text styling. The underlying OS required by SimpleText implemented a standard styled text format, which meant that SimpleText could support multiple fonts and font sizes. Prior Macintosh OS versions lacked this feature, so TeachText support


WAYNE'S WORLD 2 A film review by Michael S. Huang Copyright 1993 Michael S. Huang
Starring: Mike Myers, Dana Carvey Co-Starring: Christopher Walken, Tia Carrere, Ralph Brown Appearances by: Kim Basinger, Heather Locklear, Charleton Heston, Aerosmith, Jay Leno Written by: Mike Myers and Bonnie Turner & Jerry Turner Directed by: Stephen Surjik
Rating (0 to 10): 8.5
One year has passed since the last time we saw them, and but Wayne Campbell and Garth Algar are back but, they've moved out of their parents homes, and now have their own pad in an abandoned warehouse. Wayne's still hopelessly infatuated with his girlfriend, Cassandra, and of course Garth is still having his own, personal growing pains.
They guys are just finishing off one of their shows, and head off to an Aerosmith concert where they run across Cassandra and her new manager, a stereotypical industry slime not unlike the character Rob Lowe portrayed in the previous film.
Again, the promoter is not only after the money that Cassandra's talent can bring in. The storyline quickly degrades to a parallel of the original, "guy loses chick, guy realizes mistake, and guy gets chick back."
Fortunately, there is more to this movie than this somewhat sheer plot. The wit and humor in this film are surprisingly intelligent and fresh with many inside jokes on the film and music industries as well as just a lot of hilarious scenes of Wayne and Garth showing their true color.
Highlights of the movie include a spoof of JURASSIC PARK, Garth's seduction by a married woman, a surprise appearance by Charleton Heston, a 1960's Batman setup in the guy's pad, and some pretty groovy chats with Jim Morrison and some "naked Indian guy," an unexpected lip-sync of YMCA (you could see that one coming a mile away) and of course a hilarious parody of those badly-dubbed kung-fu movies we love to laugh at.
And if you've ever wondered why there's always boxes of watermelons, chickens, and people walking plate glass in the middle of streets, you'll find out here.
This movie also explores Wayne and Garth a little more. Garth has somewhat of a "coming of age" and Wayne gets to learn a little about himself (with a little help from our old friend, Jim Morrison). A few old jokes from the previous movie are explored here again, but this time with a few twists to keep them fresh, and luckily, few, if any of them are overused.
Overall, the movie has plenty of continuity flaws (especially in the fight scent between Garth and Cassandra's dad), but these are easily overlooked as this is, after Wayne's World. The plot is flimsy but manageable. There are a few special effects, but they are fairly seamless, and fill nicely into the plot. The acting is good, for this sort of movie, but there are some very bright spots.
In the big picture, this movie is just plain fun. There is lots of intelligent humor that makes this film special. During the whole one hour and 40 minutes, I didn't even think about looking at my watch a single time. Silly, but riotous at times, this is an excellent movie even better than the original.
Mike Huang -- Michael S. Huang<EMAIL_ADDRESS>.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


This tutorial is a step by step guide to learn how to add new properties to existing entities, from database layer to UI layer.
In ASP.NET Zero, Tenant, User and Role entities are abstract in the framework, others are not. There are some differences between them. So, we seperated it into two sections.
Note: We assume that you created your project as described in the Getting Started document.
As a sample, we will work on User entity. We want to add an Address property to the User.
Open Authorization\Users\User.cs (in .Core project) and add the new property:
public class User : AbpUser<User>
{
//...existing code
public virtual string Address { get; set; }
}
Here, we hided existing code in the User class to show it simpler. You can add Address property after existing properties.
Since we added new property, our database schema is changed. Whever we change our entities, we should add a new database migration. Open Console Package Manager and write new migration code:
Add-Migration "Added_Address_To_User"
This will create a new Entity Framework migration class:
public partial class Added_Address_To_User : DbMigration
{
public override void Up()
{
AddColumn("dbo.AbpUsers", "Address", c => c.String());
}
public override void Down()
{
DropColumn("dbo.AbpUsers", "Address");
}
}
Since it's automatically created, we don't have to know what it does for most cases. Now, we can update our database with this command:
Update-Database
When we check AbpUsers table in the database, we can see the new Address field:
For test purposes, we entered some data for existing users by hand.
Authorization\Users\UserAppService.cs (in .Application project) is used to get list of users by clients. It returns a list of UserListDto (we always use DTOs for client communication). So, we should add the Address property to UserListDto too:
[AutoMapFrom(typeof(User))]
public class UserListDto : EntityDto<long>, IPassivable, IHasCreationTime
{
//...existing code
public string Address { get; set; }
}
Since UserListDto auto maps from User entity, no need to change UserAppService.GetUsers method. Now, we can go to UI side to add Address property to the users table. Open .Web\App\common\views\users\index.js and add Address column right after Surname column:
{
name: app.localize('Surname'),
field: 'surname',
minWidth: 120
},
{
name: app.localize('Address'),
field: 'address',
minWidth: 140
},
{
name: app.localize('Roles'),
field: 'getRoleNames()',
enableSorting: false,
minWidth: 160
},
New added code is highlighted. That's all. Let's run the application and open the users page:
This was for SPA (Single Page Application with Angularjs). It's similar for MPA side. Just open .Web\Areas\Mpa\Views\Users\index.js and add Address field to the table as like Surname.
We may want to set Address while creating/editing a User.
Clients use UserAppService.GetUserForEdit method to show user information on edit form. It returns GetUserForEditOutput object which contains a UserEditDto object that includes user properties. So, we should add Address to UserEditDto to allow clients to change Address property on create/update:
public class UserEditDto : IPassivable
{
//...existing code
public string Address { get; set; }
}
Since UserAppService use auto mapping, no need to manually map Address to the User entity. So, server side code is just that. We can go to UI side to add an Address field to the form:

<input type="text" name="Address" class="form-control" ng-class="{'edited':vm.user.address}" ng-model="vm.user.address">
@L("Address")

This code is written to .Web\App\common\views\users\createOrEditModal.cshtml for SPA. For MPA, it will be similar in .Web\Areas\Mpa\Views\Users\createOrEditModal.cshtml file. You can take existing Surname property as example. After adding, new Address field is shown on the create/edit form as shown below:
Note: Since we haven't localized "Address" text, it's shown like [Address]. To fix it, you can open localization file under .Core\Localization\ExtendEntitiesDemo and add Address text as like others.
You can see this Github commit for all changes applied.
As a sample, we will work on Edition entity.
Since Edition is not abstract in the framework, we can not direcly add new properties to the Edition class. Instead, we should use OOP patterns like inheritance or composition. Since inheritance will be simpler, we can create a new class deriving from Edition entity, say MyEdition (We add this class into Editions folder under the .Core project):
public class MyEdition : Edition
{
public virtual int Price { get; set; }
}
Since we added a new entity class, our database schema is changed. Whever we change our entities, we should add a new database migration. Open Console Package Manager and write new migration code:
Add-Migration "Added_MyEdition_Entity"
This will create a new Entity Framework migration class as shown below:
public partial class Added_MyEdition_Entity : DbMigration
{
public override void Up()
{
AlterTableAnnotations(
"dbo.AbpEditions",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 32),
DisplayName = c.String(nullable: false, maxLength: 64),
IsDeleted = c.Boolean(nullable: false),
DeleterUserId = c.Long(),
DeletionTime = c.DateTime(),
LastModificationTime = c.DateTime(),
LastModifierUserId = c.Long(),
CreationTime = c.DateTime(nullable: false),
CreatorUserId = c.Long(),
Price = c.Int(),
Discriminator = c.String(nullable: false, maxLength: 128),
},
annotations: new Dictionary<string, AnnotationValues>
{
{
"DynamicFilter_MyEdition_SoftDelete",
new AnnotationValues(oldValue: null, newValue: "EntityFramework.DynamicFilters.DynamicFilterDefinition")
},
});
AddColumn("dbo.AbpEditions", "Price", c => c.Int(nullable: false, defaultValue: 0));
AddColumn("dbo.AbpEditions", "Discriminator", c => c.String(nullable: false, maxLength: 128, defaultValue: "MyEdition"));
}
public override void Down()
{
//...other code
}
}
Basically, this migration adds two new columns to AbpEditions table:
Before applying changes to the database, we changed default migration code from:
AddColumn("dbo.AbpEditions", "Price", c => c.Int());
AddColumn("dbo.AbpEditions", "Discriminator", c => c.String(nullable: false, maxLength: 128));
to:
AddColumn("dbo.AbpEditions", "Price", c => c.Int(nullable: false, defaultValue: 0));
AddColumn("dbo.AbpEditions", "Discriminator", c => c.String(nullable: false, maxLength: 128, defaultValue: "MyEdition"));
We did it since we want to replace existing Edition entities by MyEdition. Now, we can update our database with this command:
Update-Database
When we check AbpEditions table in the database, we can see the new fields:
As you see, existing 'Standard Edition' entry changed to MyEdition with Price = 0.
One last thing about migration is the database Seed code. Seed code currently creates the 'Standard edition'. We should go to .EntityFramework\Migrations\Seed\DefaultEditionCreator.cs class and change Edition creation code from:
defaultEdition = new Edition { Name = EditionManager.DefaultEditionName, DisplayName = EditionManager.DefaultEditionName };
to:
defaultEdition = new MyEdition { Name = EditionManager.DefaultEditionName, DisplayName = EditionManager.DefaultEditionName };
Thus, it creates MyEdition entity when we create database from scratch.
Editions\EditionAppService.cs (in .Application project) is used to get list of editions by clients. It returns a list of EditionListDto (we always use DTOs for client communication). So, we should add the Price property to EditionListDto too:
[AutoMapFrom(typeof(MyEdition))]
public class EditionListDto : EntityDto, IHasCreationTime
{
//...existing code
public int Price { get; set; }
}
We added auto mapping from MyEdition. No need to change EditionAppService.GetEditions method by the help of auto mapping. Now, we can go to UI side to add Price property to the editions table. Open .Web\App\host\views\editions\index.js and add Price column right after EditionName column:
{
name: app.localize('EditionName'),
field: 'displayName'
},
{
name: app.localize('Price'),
field: 'price'
},
{
name: app.localize('CreationTime'),
field: 'creationTime',
cellFilter: 'momentFormat: \'L\''
}
New added code is highlighted. That's all. Let's run the application and open the editions page (editions page is only available for host users, not tenant users):
This was for SPA (Single Page Application with Angularjs). It's similar for MPA side. Just open .Web\Areas\Mpa\Views\Editions\index.js and add Price field to the table.
We may want to add Price field to edition create/update form. Create/Update logic is implemented in EditionAppService class. GetEditionForEdit method is called by clients to fill the create/edit form. This method returns a GetEditionForEditOutput which contains EditionEditDto to transfer edition properties. So, we should add Price property to EditionEditDto class:
[AutoMap(typeof(Edition), typeof(MyEdition))]
public class EditionEditDto
{
//...existing code
public int Price { get; set; }
}
We also added auto mapping for MyEdition entity. We could directly replace Edition by MyEdition if we will never use the Edition class. We left it like that to show different usages.
Since ASP.NET Zero does not use auto mapping for creating (in CreateEditionAsync method) and updating (in UpdateEditionAsync method) editions, we should change these code too:
///...
[AbpAuthorize(AppPermissions.Pages_Editions_Create)]
protected virtual async Task CreateEditionAsync(CreateOrUpdateEditionDto input)
{
var edition = new MyEdition { DisplayName = input.Edition.DisplayName, Price = input.Edition.Price };
await _editionManager.CreateAsync(edition);
await CurrentUnitOfWork.SaveChangesAsync(); //It's done to get Id of the edition.
await SetFeatureValues(edition, input.FeatureValues);
}
[AbpAuthorize(AppPermissions.Pages_Editions_Edit)]
protected virtual async Task UpdateEditionAsync(CreateOrUpdateEditionDto input)
{
Debug.Assert(input.Edition.Id != null, "input.Edition.Id should be set.");
var edition = (MyEdition)await _editionManager.GetByIdAsync(input.Edition.Id.Value);
edition.DisplayName = input.Edition.DisplayName;
edition.Price = input.Edition.Price;
await SetFeatureValues(edition, input.FeatureValues);
}
//...
Notice the highlighted areas. First, we should create MyEdition, instead of Edition and set also Price property. In the update part, we used edition manager to get the edition. Edition manager normally works for the Edition entity. So, we should cast it to MyEdition in order to reach to the Price property.
Now, we can go the the UI part. Open .Web\App\host\views\editions\createOrEditModal.cshtml and add the following form field after the EditionName field:

<input class="form-control edited" type="number" name="EditionPrice" ng-model="vm.edition.price">
@L("Price")

It's similar for MVC side. In this case, you need to edit .Web\Areas\Mpa\Views\Editions\_CreateOrEditModal.cshtml. Now, we can edit an edition with entering the price:
You can see this Github commit for all changes applied.
In EntityFramework Core 2.0, OnModelCrreating must be used to configure extended entity if base entity contains a self reference (see https://github.com/aspnet/EntityFrameworkCore/issues/9704). An example of this case is extending OrganizationUnit entity.
You can get the full source code of this sample from the Github repository:
Extend Entities MPA Demo


|
| class | AlignedArray |
| | Aligned array type. More...
|
| |
| struct | AlignedBuffer |
| | Modifies semantics of cutlass::Array<> to provide guaranteed alignment. More...
|
| |
| class | Array< T, N, false > |
| | Statically sized array for any data type. More...
|
| |
| class | Array< T, N, true > |
| | Statically sized array for any data type. More...
|
| |
| struct | CommandLine |
| |
| class | complex |
| |
| class | ConstSubbyteReference |
| |
| struct | Coord |
| | Statically-sized array specifying Coords within a tensor. More...
|
| |
| class | cuda_exception |
| | C++ exception wrapper for CUDA cudaError_t . More...
|
| |
| struct | Distribution |
| | Distribution type. More...
|
| |
| struct | divide_assert |
| |
| struct | divides |
| |
| struct | divides< Array< half_t, N > > |
| |
| struct | divides< Array< T, N > > |
| |
| struct | FloatType |
| | Defines a floating-point type based on the number of exponent and mantissa bits. More...
|
| |
| struct | FloatType< 11, 52 > |
| |
| struct | FloatType< 5, 10 > |
| |
| struct | FloatType< 8, 23 > |
| |
| struct | half_t |
| | IEEE half-precision floating-point type. More...
|
| |
| class | HostTensor |
| | Host tensor. More...
|
| |
| class | IdentityTensorLayout |
| |
| struct | integer_subbyte |
| | 4-bit signed integer type More...
|
| |
| struct | IntegerType |
| | Defines integers based on size and whether they are signed. More...
|
| |
| struct | IntegerType< 1, false > |
| |
| struct | IntegerType< 1, true > |
| |
| struct | IntegerType< 16, false > |
| |
| struct | IntegerType< 16, true > |
| |
| struct | IntegerType< 32, false > |
| |
| struct | IntegerType< 32, true > |
| |
| struct | IntegerType< 4, false > |
| |
| struct | IntegerType< 4, true > |
| |
| struct | IntegerType< 64, false > |
| |
| struct | IntegerType< 64, true > |
| |
| struct | IntegerType< 8, false > |
| |
| struct | IntegerType< 8, true > |
| |
| struct | is_pow2 |
| |
| struct | KernelLaunchConfiguration |
| | Structure containing the basic launch configuration of a CUDA kernel. More...
|
| |
| struct | log2_down |
| |
| struct | log2_down< N, 1, Count > |
| |
| struct | log2_up |
| |
| struct | log2_up< N, 1, Count > |
| |
| struct | MatrixCoord |
| |
| struct | MatrixShape |
| | Describes the size of a matrix tile. More...
|
| |
| struct | Max |
| |
| struct | maximum |
| |
| struct | maximum< Array< T, N > > |
| |
| struct | maximum< float > |
| |
| struct | Min |
| |
| struct | minimum |
| |
| struct | minimum< Array< T, N > > |
| |
| struct | minimum< float > |
| |
| struct | minus |
| |
| struct | minus< Array< half_t, N > > |
| |
| struct | minus< Array< T, N > > |
| |
| struct | multiplies |
| |
| struct | multiplies< Array< half_t, N > > |
| |
| struct | multiplies< Array< T, N > > |
| |
| struct | multiply_add |
| | Fused multiply-add. More...
|
| |
| struct | multiply_add< Array< half_t, N >, Array< half_t, N >, Array< half_t, N > > |
| | Fused multiply-add. More...
|
| |
| struct | multiply_add< Array< T, N >, Array< T, N >, Array< T, N > > |
| | Fused multiply-add. More...
|
| |
| struct | multiply_add< complex< T >, complex< T >, complex< T > > |
| | Fused multiply-add. More...
|
| |
| struct | multiply_add< complex< T >, T, complex< T > > |
| | Fused multiply-add. More...
|
| |
| struct | multiply_add< T, complex< T >, complex< T > > |
| | Fused multiply-add. More...
|
| |
| struct | negate |
| |
| struct | negate< Array< half_t, N > > |
| |
| struct | negate< Array< T, N > > |
| |
| struct | NumericArrayConverter |
| | Conversion operator for Array. More...
|
| |
| struct | NumericArrayConverter< float, half_t, 2, Round > |
| | Partial specialization for Array<float, 2> <= Array<half_t, 2>, round to nearest. More...
|
| |
| struct | NumericArrayConverter< float, half_t, N, Round > |
| | Partial specialization for Array<half> <= Array<float> More...
|
| |
| struct | NumericArrayConverter< half_t, float, 2, FloatRoundStyle::round_to_nearest > |
| | Partial specialization for Array<half, 2> <= Array<float, 2>, round to nearest. More...
|
| |
| struct | NumericArrayConverter< half_t, float, N, Round > |
| | Partial specialization for Array<half> <= Array<float> More...
|
| |
| struct | NumericConverter |
| |
| struct | NumericConverter< float, half_t, Round > |
| | Partial specialization for float <= half_t. More...
|
| |
| struct | NumericConverter< half_t, float, FloatRoundStyle::round_to_nearest > |
| | Specialization for round-to-nearest. More...
|
| |
| struct | NumericConverter< half_t, float, FloatRoundStyle::round_toward_zero > |
| | Specialization for round-toward-zero. More...
|
| |
| struct | NumericConverter< int8_t, float, Round > |
| |
| struct | NumericConverter< T, T, Round > |
| | Partial specialization for float <= half_t. More...
|
| |
| struct | NumericConverterClamp |
| |
| struct | plus |
| |
| struct | plus< Array< half_t, N > > |
| |
| struct | plus< Array< T, N > > |
| |
| struct | PredicateVector |
| | Statically sized array of bits implementing. More...
|
| |
| struct | RealType |
| | Used to determine the real-valued underlying type of a numeric type T. More...
|
| |
| struct | RealType< complex< T > > |
| | Partial specialization for complex-valued type. More...
|
| |
| struct | ReferenceFactory |
| |
| struct | ReferenceFactory< Element, false > |
| |
| struct | ReferenceFactory< Element, true > |
| |
| struct | ScalarIO |
| | Helper to enable formatted printing of CUTLASS scalar types to an ostream. More...
|
| |
| class | Semaphore |
| | CTA-wide semaphore for inter-CTA synchronization. More...
|
| |
| struct | sizeof_bits |
| | Defines the size of an element in bits. More...
|
| |
| struct | sizeof_bits< Array< T, N, RegisterSized > > |
| | Statically sized array for any data type. More...
|
| |
| struct | sizeof_bits< bin1_t > |
| | Defines the size of an element in bits - specialized for bin1_t. More...
|
| |
| struct | sizeof_bits< int4b_t > |
| | Defines the size of an element in bits - specialized for int4b_t. More...
|
| |
| struct | sizeof_bits< uint1b_t > |
| | Defines the size of an element in bits - specialized for uint1b_t. More...
|
| |
| struct | sizeof_bits< uint4b_t > |
| | Defines the size of an element in bits - specialized for uint4b_t. More...
|
| |
| struct | sqrt_est |
| |
| class | SubbyteReference |
| |
| struct | Tensor4DCoord |
| | Defines a canonical 4D coordinate used by tensor operations. More...
|
| |
| class | TensorRef |
| |
| class | TensorView |
| |
| struct | TypeTraits |
| |
| struct | TypeTraits< complex< double > > |
| |
| struct | TypeTraits< complex< float > > |
| |
| struct | TypeTraits< complex< half > > |
| |
| struct | TypeTraits< complex< half_t > > |
| |
| struct | TypeTraits< double > |
| |
| struct | TypeTraits< float > |
| |
| struct | TypeTraits< half_t > |
| |
| struct | TypeTraits< int > |
| |
| struct | TypeTraits< int64_t > |
| |
| struct | TypeTraits< int8_t > |
| |
| struct | TypeTraits< uint64_t > |
| |
| struct | TypeTraits< uint8_t > |
| |
| struct | TypeTraits< unsigned > |
| |
| struct | xor_add |
| | Fused multiply-add. More...
|
| |
|
| CUTLASS_HOST_DEVICE constexpr bool | ispow2 (unsigned x) |
| | Returns true if the argument is a power of 2. More...
|
| |
| CUTLASS_HOST_DEVICE constexpr unsigned | floor_pow_2 (unsigned x) |
| | Returns the largest power of two not greater than the argument. More...
|
| |
| CUTLASS_HOST_DEVICE float const & | real (cuFloatComplex const &z) |
| | Returns the real part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE float & | real (cuFloatComplex &z) |
| | Returns the real part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE double const & | real (cuDoubleComplex const &z) |
| | Returns the real part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE double & | real (cuDoubleComplex &z) |
| | Returns the real part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE float const & | imag (cuFloatComplex const &z) |
| | Returns the imaginary part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE float & | imag (cuFloatComplex &z) |
| | Returns the imaginary part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE double const & | imag (cuDoubleComplex const &z) |
| | Returns the imaginary part of the complex number. More...
|
| |
| CUTLASS_HOST_DEVICE double & | imag (cuDoubleComplex &z) |
| | Returns the imaginary part of the complex number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T const & | real (complex< T > const &z) |
| | Returns the real part of the complex number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T & | real (complex< T > &z) |
| | Returns the real part of the complex number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T const & | imag (complex< T > const &z) |
| | Returns the imaginary part of the complex number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T & | imag (complex< T > &z) |
| | Returns the imaginary part of the complex number. More...
|
| |
| template<typename T > |
| std::ostream & | operator<< (std::ostream &out, complex< T > const &z) |
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T | abs (complex< T > const &z) |
| | Returns the magnitude of the complex number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T | arg (complex< T > const &z) |
| | Returns the magnitude of the complex number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE T | norm (T const &z) |
| | Returns the squared magnitude of a real number. More...
|
| |
| template<> |
| CUTLASS_HOST_DEVICE int8_t | norm (int8_t const &z) |
| | Returns the squared magnitude of a real number. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE double | norm (complex< T > const &z) |
| | Returns the squared magnitude of a complex number. More...
|
| |
| template<typename T , typename R > |
| CUTLASS_HOST_DEVICE R | norm_accumulate (T const &x, R const &accumulator) |
| | Norm-accumulate calculation. More...
|
| |
| template<typename T , typename R > |
| CUTLASS_HOST_DEVICE R | norm_accumulate (complex< T > const &z, R const &accumulator) |
| | Norm accumulate specialized for complex types. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | conj (complex< T > const &z) |
| | Returns the complex conjugate. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | proj (complex< T > const &z) |
| | Projects the complex number z onto the Riemann sphere. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | polar (T const &r, T const &theta=T()) |
| | Returns a complex number with magnitude r and phase theta. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | exp (complex< T > const &z) |
| | Computes the complex exponential of z. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | log (complex< T > const &z) |
| | Computes the complex exponential of z. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | log10 (complex< T > const &z) |
| | Computes the complex exponential of z. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | sqrt (complex< T > const &z) |
| | Computes the square root of complex number z. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | cos (complex< T > const &z) |
| | Computes the cosine of complex z. More...
|
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE complex< T > | sin (complex< T > const &z) |
| | Computes the sin of complex z. More...
|
| |
| template<> |
| CUTLASS_HOST_DEVICE cutlass::complex< half_t > | from_real< cutlass::complex< half_t > > (double r) |
| |
| template<> |
| CUTLASS_HOST_DEVICE cutlass::complex< float > | from_real< cutlass::complex< float > > (double r) |
| |
| template<> |
| CUTLASS_HOST_DEVICE cutlass::complex< double > | from_real< cutlass::complex< double > > (double r) |
| |
| template<int Rank, typename Index > |
| CUTLASS_HOST_DEVICE Coord< Rank, Index > | operator/ (Index s, Coord< Rank, Index > coord) |
| | Scalar division. More...
|
| |
| template<int Rank, typename Index > |
| CUTLASS_HOST_DEVICE Coord< Rank, Index > | operator/ (Coord< Rank, Index > coord, Index s) |
| | Scalar division. More...
|
| |
| CUTLASS_HOST_DEVICE Coord< 1 > | make_Coord (int _0) |
| | Helper to make a 2-element coordinate. More...
|
| |
| CUTLASS_HOST_DEVICE Coord< 2 > | make_Coord (int _0, int _1) |
| | Helper to make a 2-element coordinate. More...
|
| |
| CUTLASS_HOST_DEVICE Coord< 3 > | make_Coord (int _0, int _1, int _2) |
| | Helper to make a 3-element coordinate. More...
|
| |
| CUTLASS_HOST_DEVICE Coord< 4 > | make_Coord (int _0, int _1, int _2, int _3) |
| | Helper to make a 4-element coordinate. More...
|
| |
| template<int Rank> |
| std::ostream & | operator<< (std::ostream &out, Coord< Rank > const &coord) |
| |
| std::istream & | operator>> (std::istream &stream, half_t &x) |
| |
| std::ostream & | operator<< (std::ostream &out, half_t const &x) |
| |
| template<typename T > |
| std::ostream & | operator<< (std::ostream &out, ScalarIO< T > const &scalar) |
| | Default printing to ostream. More...
|
| |
| template<> |
| std::ostream & | operator<< (std::ostream &out, ScalarIO< int8_t > const &scalar) |
| | Printing to ostream of int8_t as integer rather than character. More...
|
| |
| template<> |
| std::ostream & | operator<< (std::ostream &out, ScalarIO< uint8_t > const &scalar) |
| | Printing to ostream of uint8_t as integer rather than character. More...
|
| |
| template<typename Operator > |
| __global__ void | Kernel (typename Operator::Params params) |
| | Generic CUTLASS kernel template. More...
|
| |
| template<typename dividend_t , typename divisor_t > |
| CUTLASS_HOST_DEVICE dividend_t | round_nearest (dividend_t dividend, divisor_t divisor) |
| |
| template<typename value_t > |
| CUTLASS_HOST_DEVICE value_t | gcd (value_t a, value_t b) |
| |
| template<typename value_t > |
| CUTLASS_HOST_DEVICE value_t | lcm (value_t a, value_t b) |
| |
| template<typename value_t > |
| CUTLASS_HOST_DEVICE value_t | clz (value_t x) |
| |
| template<typename value_t > |
| CUTLASS_HOST_DEVICE value_t | find_log2 (value_t x) |
| |
| CUTLASS_HOST_DEVICE void | find_divisor (unsigned int &mul, unsigned int &shr, unsigned int denom) |
| |
| CUTLASS_HOST_DEVICE void | fast_divmod (int &quo, int &rem, int src, int div, unsigned int mul, unsigned int shr) |
| |
| CUTLASS_HOST_DEVICE void | fast_divmod (int &quo, int64_t &rem, int64_t src, int div, unsigned int mul, unsigned int shr) |
| |
| CUTLASS_HOST_DEVICE constexpr int | const_min (int a, int b) |
| |
| CUTLASS_HOST_DEVICE constexpr int | const_max (int a, int b) |
| |
| CUTLASS_HOST_DEVICE bool | signbit (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE cutlass::half_t | abs (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE bool | isnan (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE bool | isfinite (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE cutlass::half_t | nanh (const char *) |
| |
| CUTLASS_HOST_DEVICE bool | isinf (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE bool | isnormal (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE int | fpclassify (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE cutlass::half_t | sqrt (cutlass::half_t const &h) |
| |
| CUTLASS_HOST_DEVICE half_t | copysign (half_t const &a, half_t const &b) |
| |
| CUTLASS_HOST_DEVICE bool | operator== (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE bool | operator!= (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE bool | operator< (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE bool | operator<= (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE bool | operator> (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE bool | operator>= (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t | operator+ (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t | operator- (half_t const &lhs) |
| |
| CUTLASS_HOST_DEVICE half_t | operator- (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t | operator* (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t | operator/ (half_t const &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t & | operator+= (half_t &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t & | operator-= (half_t &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t & | operator*= (half_t &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t & | operator/= (half_t &lhs, half_t const &rhs) |
| |
| CUTLASS_HOST_DEVICE half_t & | operator++ (half_t &lhs) |
| |
| CUTLASS_HOST_DEVICE half_t & | operator-- (half_t &lhs) |
| |
| CUTLASS_HOST_DEVICE half_t | operator++ (half_t &lhs, int) |
| |
| CUTLASS_HOST_DEVICE half_t | operator-- (half_t &lhs, int) |
| |
| template<typename T > |
| CUTLASS_HOST_DEVICE bool | relatively_equal (T a, T b, T epsilon, T nonzero_floor) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< uint1b_t > (uint1b_t a, uint1b_t b, uint1b_t, uint1b_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< int4b_t > (int4b_t a, int4b_t b, int4b_t, int4b_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< uint4b_t > (uint4b_t a, uint4b_t b, uint4b_t, uint4b_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< int8_t > (int8_t a, int8_t b, int8_t, int8_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< uint8_t > (uint8_t a, uint8_t b, uint8_t, uint8_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< int16_t > (int16_t a, int16_t b, int16_t, int16_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< uint16_t > (uint16_t a, uint16_t b, uint16_t, uint16_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< int32_t > (int32_t a, int32_t b, int32_t, int32_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< uint32_t > (uint32_t a, uint32_t b, uint32_t, uint32_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< int64_t > (int64_t a, int64_t b, int64_t, int64_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< uint64_t > (uint64_t a, uint64_t b, uint64_t, uint64_t) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< half_t > (half_t a, half_t b, half_t epsilon, half_t nonzero_floor) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< float > (float a, float b, float epsilon, float nonzero_floor) |
| |
| template<> |
| CUTLASS_HOST_DEVICE bool | relatively_equal< double > (double a, double b, double epsilon, double nonzero_floor) |
| |
| template<typename Element , typename Layout > |
| CUTLASS_HOST_DEVICE TensorRef< Element, Layout > | make_TensorRef (Element *ptr, Layout const &layout) |
| | Constructs a TensorRef, deducing types from arguments. More...
|
| |
| template<typename Element , typename Layout > |
| bool | TensorRef_aligned (TensorRef< Element, Layout > const &ref, int alignment) |
| |
| template<typename Element , typename Layout > |
| CUTLASS_HOST_DEVICE TensorView< Element, Layout > | make_TensorView (Element *ptr, Layout const &layout, typename Layout::TensorCoord const &extent) |
| | Constructs a TensorRef, deducing types from arguments. More...
|
| |
| __host__ CUTLASS_DEVICE cudaError_t | cuda_perror_impl (cudaError_t error, const char *filename, int line) |
| | The corresponding error message is printed to stderr (or stdout in device code) along with the supplied source context. More...
|
| |
| std::ostream & | operator<< (std::ostream &out, cudaError_t result) |
| | Writes a cudaError_t to an output stream. More...
|
| |
| std::ostream & | operator<< (std::ostream &out, cuda_exception const &e) |
| | Writes a cuda_exception instance to an output stream. More...
|
| |
| template<int Interleaved, typename Element , typename Layout > |
| void | reorder_column (TensorRef< Element, Layout > dest, TensorRef< Element, Layout > src, cutlass::gemm::GemmCoord problem_size) |
| |
| template<typename Element , typename Layout > |
| std::ostream & | TensorViewWrite (std::ostream &out, TensorView< Element, Layout > const &view) |
| | Prints human-readable representation of a TensorView to an ostream. More...
|
| |
| template<typename Element , typename Layout > |
| std::ostream & | operator<< (std::ostream &out, TensorView< Element, Layout > const &view) |
| | Prints human-readable representation of a TensorView to an ostream. More...
|
| |


Add new product
Name product:
Price product:
Add Color:
Add color
Delete Color:
Delete color {{colorA}}
Size:
{{size.$value}}
Add size
Delete size:
Delete size {{sizeA}}
Tag:
{{tagA.$value}}
Description
Save


module Prop
Overview
Prop utilities.
Mixin module that should be included in a class or a struct.
This module improves the std's accessor macros (getter
, getter!
, getter?
, property
, ...).
If a block is defined to an instance variable, it will be executed on the
initialization of the instance (called by each initialize
).
property my_var : String = "default value" do |default_value|
# Remove leading and trailing whitespace
# " hello ".strip # => "hello"
@my_var = @my_var.strip
end
You can provide arguments:
property my_var : String = "default value", "any type of argument" do |default_value, args|
puts args
@my_var = @my_var.strip
end
The behavior can easily be extended:
module CustomProp
macro included
include Prop
macro finished
{% verbatim do %}
{% for k, prop in PROPS %}
{% if prop[:args] %}
some_ioc_method({{prop[:name]}}: { {{prop[:args].double_splat}} })
{% end %}
{% end %}
{% end %}
end
end
end
See README for more details.
If you are looking for a validator to validate data before instantiating a class or a struct,
you may be interested by validator.
This validator shard uses Prop
internally
to define and handle validation rules on each instance variable.


Grab raw product links here
Which product website are you searching?
Determine a product's claim to be ES Certified
Search products of interest with Energy Star
Search world wide web for hits here
Starting seeds


Mirror
Through the looking glass
Screenshot
Broadcast
Screenshot
Flip
Threshold
You are talking to:
broadcast
broadcast
There are
0
users online.


Microservice Modeler - Releases Repository
This is an Eclipse update site/p2 repository providing all the releases of these versions. You should access it from Eclipse by using the following URL:
http://thlaegler.github.io/microservice-modeler/eclipse/latest/


Three days later I’m still impressed with the Palm Pre. As a user of Palm OS smartphones (Treo 600, Treo 650, Centro), I’ve come to rely on a proven feature set. The experience of having a device that organizes your life, makes phone calls, and connects online — has remained unchanged. For the most part the Palm Pre meets or exceeds my expectations, with only a few minor back steps. After the break is a full rundown of my Palm Pre likes and dislikes (mostly software related), in no particular order.
Palm Pre positives
- Device feels great in your hands. (Not sure where all the “it feels cheap” reviews came from.)
- Screen looks awesome!
- The UI is very slick.
- webOS is very responsive and allows true multitasking.
- Notifications are handled very elegantly.
- Push Gmail. (Emails hit my Palm Pre before my desktop — sweet!)
- Synergy and the way that it syncs with “the cloud.” (ie: Google, Facebook, etc)
- Battery life. (I can easily make it through a workday which is all I had hoped for)
- Removable battery.
- Physical keyboard. (Yes it’s small, but coming from a Centro I have no problems banging out txts or emails.)
- Plugging in via USB let’s you access the ringtone and wallpaper folders, to easily add your own to the device.
- Is capable of syncing with iTunes to add music, podcasts, videos, movies, or photos.
- Backups every day to your Palm Profile — just in case you need to restore your device after a wipe.
- GPS and Sprint Navigation for turn by turn directions.
Palm Pre negatives
- Having to pay $30 for the Classic app. Booooooooo!
- Having to use Classic at all! Let’s get true webOS versions on the App Catalog so I can stop using Classic for a few archaic applications.
- No option to make Tasks repeatable like the Palm OS version. (Maybe I’m the only one who relies on this — I dunno)
- Tasks don’t sync up with Google Tasks. (I’m sure this will happen eventually)
- Flipping through the Calendar is painfully slow.
- No agenda view in Calendar.
- Sprint Navigation doesn’t pull in your contacts’ addresses if they’re coming from Google or Facebook accounts.
- Can’t change the notification sound. (I have no desire to change it but it would be nice to have the option)
- Can’t assign a default ringtone for unknown callers like in Palm OS devices.
- Reception issues. (I’ve never had more than 2 bars at my house with the Centro, but the Palm Pre seems to average much less and I’ve experienced a few dropped calls)
- Landscape mode is limited to only a few applications
- USB port cover seems cheaply made and I feel like I’m going to break it off every time I open it.
- Device does get warm after prolonged usage. (To be fair so did my Centro)
- Audio speaker isn’t that loud.
So there you have it. Can’t say that I was excited about the thought of paying an extra $20 a month for the required Sprint Everything Data plan. But seeing how I’m getting more anytime minutes, Sprint Navigation, Sprint TV, and nights that start at 7pm instead of 9pm — I’ll live. My only real Palm Pre complaints stem from its software or lack of applications, which I’m pretty confident will be addressed with future firmware and software updates. I hope ;-)
If you’re looking for a more in-depth look at the Palm Pre, check out Precentral’s extensive review. They cover every aspect of the phone with a detailed write-up, photos, and video walkthroughs.


Apache HTTP Server 版本2.2
| 说明 | 为每个请求生成唯一的标识以便跟踪 |
|---|---|
| 状态 | 扩展(E) |
| 模块名 | unique_id_module |
| 源文件 | mod_unique_id.c |
This module provides a magic token for each request which is
guaranteed to be unique across "all" requests under very
specific conditions. The unique identifier is even unique
across multiple machines in a properly configured cluster of
machines. The environment variable UNIQUE_ID
is
set to the identifier for each request. Unique identifiers are
useful for various reasons which are beyond the scope of this
document.
First a brief recap of how the Apache server works on Unix machines. This feature currently isn't supported on Windows NT. On Unix machines, Apache creates several children, the children process requests one at a time. Each child can serve multiple requests in its lifetime. For the purpose of this discussion, the children don't share any data with each other. We'll refer to the children as httpd processes.
Your website has one or more machines under your administrative control, together we'll call them a cluster of machines. Each machine can possibly run multiple instances of Apache. All of these collectively are considered "the universe", and with certain assumptions we'll show that in this universe we can generate unique identifiers for each request, without extensive communication between machines in the cluster.
The machines in your cluster should satisfy these requirements. (Even if you have only one machine you should synchronize its clock with NTP.)
As far as operating system assumptions go, we assume that pids (process ids) fit in 32-bits. If the operating system uses more than 32-bits for a pid, the fix is trivial but must be performed in the code.
Given those assumptions, at a single point in time we can identify any httpd process on any machine in the cluster from all other httpd processes. The machine's IP address and the pid of the httpd process are sufficient to do this. So in order to generate unique identifiers for requests we need only distinguish between different points in time.
To distinguish time we will use a Unix timestamp (seconds since January 1, 1970 UTC), and a 16-bit counter. The timestamp has only one second granularity, so the counter is used to represent up to 65536 values during a single second. The quadruple ( ip_addr, pid, time_stamp, counter ) is sufficient to enumerate 65536 requests per second per httpd process. There are issues however with pid reuse over time, and the counter is used to alleviate this issue.
When an httpd child is created, the counter is initialized with ( current microseconds divided by 10 ) modulo 65536 (this formula was chosen to eliminate some variance problems with the low order bits of the microsecond timers on some systems). When a unique identifier is generated, the time stamp used is the time the request arrived at the web server. The counter is incremented every time an identifier is generated (and allowed to roll over).
The kernel generates a pid for each process as it forks the process, and pids are allowed to roll over (they're 16-bits on many Unixes, but newer systems have expanded to 32-bits). So over time the same pid will be reused. However unless it is reused within the same second, it does not destroy the uniqueness of our quadruple. That is, we assume the system does not spawn 65536 processes in a one second interval (it may even be 32768 processes on some Unixes, but even this isn't likely to happen).
Suppose that time repeats itself for some reason. That is, suppose that the system's clock is screwed up and it revisits a past time (or it is too far forward, is reset correctly, and then revisits the future time). In this case we can easily show that we can get pid and time stamp reuse. The choice of initializer for the counter is intended to help defeat this. Note that we really want a random number to initialize the counter, but there aren't any readily available numbers on most systems (i.e., you can't use rand() because you need to seed the generator, and can't seed it with the time because time, at least at one second resolution, has repeated itself). This is not a perfect defense.
How good a defense is it? Suppose that one of your machines serves at most 500 requests per second (which is a very reasonable upper bound at this writing, because systems generally do more than just shovel out static files). To do that it will require a number of children which depends on how many concurrent clients you have. But we'll be pessimistic and suppose that a single child is able to serve 500 requests per second. There are 1000 possible starting counter values such that two sequences of 500 requests overlap. So there is a 1.5% chance that if time (at one second resolution) repeats itself this child will repeat a counter value, and uniqueness will be broken. This was a very pessimistic example, and with real world values it's even less likely to occur. If your system is such that it's still likely to occur, then perhaps you should make the counter 32 bits (by editing the code).
You may be concerned about the clock being "set back" during summer daylight savings. However this isn't an issue because the times used here are UTC, which "always" go forward. Note that x86 based Unixes may need proper configuration for this to be true -- they should be configured to assume that the motherboard clock is on UTC and compensate appropriately. But even still, if you're running NTP then your UTC time will be correct very shortly after reboot.
UNIQUE_ID
environment variable is
constructed by encoding the 112-bit (32-bit IP address, 32 bit
pid, 32 bit time stamp, 16 bit counter) quadruple using the
alphabet [A-Za-z0-9@-]
in a manner similar to MIME
base64 encoding, producing 19 characters. The MIME base64
alphabet is actually [A-Za-z0-9+/]
however
+
和/
need to be specially encoded
in URLs, which makes them less desirable. All values are
encoded in network byte ordering so that the encoding is
comparable across architectures of different byte ordering. The
actual ordering of the encoding is: time stamp, IP address,
pid, counter. This ordering has a purpose, but it should be
emphasized that applications should not dissect the encoding.
Applications should treat the entire encoded
UNIQUE_ID
as an opaque token, which can be
compared against other UNIQUE_ID
s for equality
only.
The ordering was chosen such that it's possible to change
the encoding in the future without worrying about collision
with an existing database of UNIQUE_ID
s. The new
encodings should also keep the time stamp as the first element,
and can otherwise use the same alphabet and bit length. Since
the time stamps are essentially an increasing sequence, it's
sufficient to have a flag second in which all machines
in the cluster stop serving and request, and stop using the old
encoding format. Afterwards they can resume requests and begin
issuing the new encodings.
This we believe is a relatively portable solution to this problem. It can be extended to multithreaded systems like Windows NT, and can grow with future needs. The identifiers generated have essentially an infinite life-time because future identifiers can be made longer as required. Essentially no communication is required between machines in the cluster (only NTP synchronization is required, which is low overhead), and no communication between httpd processes is required (the communication is implicit in the pid value assigned by the kernel). In very specific situations the identifier can be shortened, but more information needs to be assumed (for example the 32-bit IP address is overkill for any site, but there is no portable shorter replacement for it).


ChordAL
Chord-Based Learning Framework for Symbolic Music Generation using Neural Networks
Generation by Chord
{% include 'generation.html' %}


Book Trader
menu
UPDATE BOOK
DELETE BOOK
PROFILE
CART
ORDER
ADD COMMENT
ALL COMMENTS
Add to Cart
Buy It
Purchase Book
Quantity:
Address:
Add Comment
Rate(1-5):
Comment:
Please Confirm: Do you want to add this book
Update A Book
ISBN:
Title:
Author:
Price:


Kodenames
Reset
confirm?
Default Word Set
Spanish Word Set
2K Nouns
Top 250 Movies
Custom Words
SpyMaster
Icons made by
ultimatearm
from
www.flaticon.com


---
title: "49+ Camera Light Logo
Gif"
description: "Lighting is crucial when it comes to capturing videos."
date: "2020-06-08"
categories:
- "Logo"
images:
- "https://ungerandkowitt.com/wp-content/uploads/2016/09/youzign-23-660x449.png"
featuredImage: "https://library.kissclipart.com/20180918/fue/kissclipart-film-light-icon-clipart-photographic-film-light-cl-861ad48ad0bf57ff.png"
featured_image: "https://img.favpng.com/3/12/18/brand-logo-automotive-design-technology-png-favpng-k41Ltryjtyh3eFKATrUdRim8b.jpg"
image: "https://assets.website-files.com/5f1b4e0ceb171b0d90626d91/5f1f3d592d494776104e8bb2_5e17fddeb827fa34df539544_light_logo_dark.svg"
---
49+ Camera Light Logo
Gif. Free vector icons in svg, psd, png, eps and icon font. Awesome camera light logo intro i will create awesome intro video for your:
Camera logo hd png you can download 30 free camera logo hd png images. Upload your logo and get a professional animation in a few minutes. 1,000+ vectors, stock photos & psd files.
In addition, all trademarks and usage rights belong to the.
The virtual studio is completely set up to illuminate your brandmark. We have 67 free camera vector logos, logo templates and icons. You can download in.ai,.eps,.cdr,.svg,.png formats. There is no psd format for png camera logo in our system.


You are trying to visit Amazon with this affiliate ID:
beckism-20
Keep affiliate tag Strip affiliate tag


This is the body section of our blog post. In this section I will write about things. I'll be sure to use the HTML tags I have been learning to use.
This is another paragraph, and U would like to quote the late, great Martin Luther King Jr. who once said I have a dream
.
I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation.
Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity.


--- title: "People" date: 2020-06-12T12:57:28+08:00 draft: false ---
Final Year Student
Division of Psychology, School of Social Sciences
Nanyang Technological University
(to-be added)
First Year Student
Division of Psychology and Language Sciences, Faculty of Brain Sciences
University College London
(to-be added)
Third Year Student
School of Biological Sciences
Nanyang Technological University
(to-be added)


GoFlow Documentation
¶
Contents
¶
Overview
Preface
Summary
Overview
Benefits of using GoFlow
The Process Definition
The Process Instance
Features
Requirements
Download
Workflow Patterns
Sequence Pattern
XOR-Join Pattern
XOR-Split Pattern
AND-Join Pattern
AND-Split Pattern
GoFlow User Guide
Prerequisites
Project “Hello World”
Advanced Tutorial
Installation
Python
Django
GoFlow
Optional (but useful) Modules
GoFlow FAQ
What is this all about?
When should I use PushApplication and when should I use Roles in Activity definition? What happens if I select both?
What are AutoStart and AutoFinish in Activity definition
How should I define a transition condition ?
Is it valid to reuse Activities?
What’s new
Release 0.51
History
Origins
Roadmap
Current Status
Future Features
GoFlow License
GoFlow Credits
Definitions
Introduction & Concepts
Definitions
Activity Types
AutoRouting & Interactiveness
Sample Process
Modules
GoFlow Modules
goflow
Indices and tables
Glossary
Application
PushApplication
User
Activity
Role
Activity-based Workflow
Process
Transitions
Workflow
ProcessInstance
WorkItem
Indices and tables
¶
Index
Module Index
Search Page
Table Of Contents
GoFlow Documentation
Contents
Indices and tables
Related Topics
Documentation overview
Next:
Overview
This Page
Show Source
Quick search


That's not a valid redirect. If you followed a link here, yell at whoever sent it to you. Unless it was me, in which case... oops.
Me // Source // Twitter // Keybase // Admin


Henry's Library
Add A Book
Title
Author
Binding
Source
Date Added
{{range .}}
{{.Title}}
{{.Author}}
{{.Binding}}
{{.Source}}
{{.DateAdded.Format "02 Jan 2006"}}
update
delete
{{end}}


Week 4 Crystal Game
Click on a crystal to increase the value, but don't go over the target.
Number to Guess:
Wins:
Losses:
Your Score is:


This image of Fort Irwin in California's Mojave Desert compares interferometric radar signatures topography -- data that were obtained by multiple imaging of the same region to produce three-dimensional elevation maps -- as it was obtained on October 7-8, 1994 by the Spaceborne Imaging Radar-C/X-band Synthetic Aperture Radar aboard the space shuttle Endeavour. Data were acquired using the L-band (24 centimeter wavelength) and C-band (6 centimeter wavelength). The image covers an area about 25 kilometers by 70 kilometers (15.5 miles by 43 miles). North is to the lower right of the image. The color contours shown are proportional to the topographic elevation. With a wavelength one-fourth that of the L-band, the results from the C-band cycle through the color contours four times faster for a given elevation change. Detailed comparisions of these multiple frequency data over different terrain types will provide insights in the future into wavelength-dependent effects of penetration and scattering on the topography measurement accuracy. Fort Irwin is an ideal site for such detailed digital elevation model comparisions because a number of high precision digital models of the area already exist from conventional measurements as well as from airborne interferometric SAR data.
P-44754 October 12, 1994


coopCmd -p:8 -c:"Selection_Move \"c:\Project\foo.txt\" target:\"c:\Project\SubDir\""
When using full version of Beyond Compare, allow diffing binary files also in history
Right-clicking on a file selection in history pane incorrectly displayed "Properties" item
Project>Invite displayed incorrect error when there was a problem in the "Advanced" page
The filter button in file view didn't always work correctly. It was supposed to hide non-project files
Executing a script that makes a file uncontrolled didn't change its status to read/write
Incorrect information popup when the admin changed check-out notification status of a user
Check in area displayed files whose type has been changed as unchanged
Adding a whole folder tree to the project would sometimes assert
When using full version of Beyond Compare, allow diffing binary files
Re-adding a locally deleted file is treated as a modification to that file. This enables the following scenario:
POP3: improved deleting corrupted messages from server
File treeview not refreshed correctly after uncheckout
Dragging from file pane sometimes picked up selection from treeview pane
Joining your first project hit assertions because UI was not correctly refreshed
Title bar was refreshed only after project verification, which may take a long time
Fixed assertions when using some command-line applets
StartCoopBackup applet didn't report some errors
Backup and Restore Code Co-op database (Pro only)
Re-create project from archived history (Pro only)
Check-out notifications (in version Pro)
Simplified script conflict UI
Rationalized setup after installation (first use brings up Dispatcher Wizard)
Added FTP support for exporting project version and history export (Pro only)
Added search with shell (uses Windows desktop search engine)
Added Selection>Properties in file view (showing who has the file checked out)
Added Project>"Configure Dispatching" to Code Co-op menu
Project>Repair works even with pending sync/merge
Command line: added "inbox" to reports
More efficient handling of large files
Added program option to quietly ignore script conflicts when the current member's scripts are not rejected
Allow cration of co-op database on a USB drive
Added Project>Open Invitation for use with exported invitations (in version Pro, LAN and FTP download supported)
Display how many chunks are missing for a missing script
Scripts that cannot be executed because of corruption are removed and marked as missing
Asynchronous merging when executing script didn't work correctly
Command line: checkin left unchanged files out
Diffing didn't work when file path contained special characters
Searching history by phrase now also displays labels
Receiving join request when waiting for full sync caused havoc
Prevent the creation of a full synch by a new administrator with incomplete membership information.
Merging scripts that created folders occasionally added orphan files to the project (files without parent folders).
Project>Repair couldn't deal with orphan files.
The error "cannot open file switch.bin" was occasionally reported. This was happening because a global semaphore was not visible to all processes.
Menu Project>Verify Paths: Verifies if all project root directories are present. In case a project root is on a removable or network drive that is absent, allows recreating the project at a different location.
When entering a project that doesn't exist on disk, offer recreating it at a different location.
Project>Repair deals with more cases of corrupt membership.
Add shell association to open .wiki files with built-in differ.
Fixed BCMerge bug: auto merge didn't write the result to target file.
Defecting from a project before receiving full sync was impossible.
Fixed a deadlock in the background instance of Code Co-op.
MS Access database modifies files while they are being checked in, resulting in a corrupt script. Calculate the checksum before and after to avoid corruption.
Downloading an invitation twice from FTP site resulted in a strange state.
Killing Code Co-op when quietly accepting invitation made further progress impossible.
After the change of e-mail address and purging the Dispatcher's address DB, scripts sent to the old e-mail address were not accepted.
Fixed unknown recipient Dispatcher dialog in Code Co-op Lite.
Corrupted full sync in chunks caused problems when a resend request was to be created.
Folders were not correctly displayed in the script details pane.
New option to save large project invitation to disk or to an FTP site for the new user to pick up.
Option to save the history during invitation (disk or FTP).
When switching from Observer to Voting Member, a verification request is sent to another project member and the check-ins are temporarily blocked (prevents ex-observers from wreaking havoc with their out-of-sequence check-ins).
Option to send a verification request from the menu to force synchronization of states between users.
A more informative script conflict dialog with the option to auto-merge on the spot.
When visiting inaccessible project (source tree absent), an option to move the project to another location.
Command line method to update hub ID in all projects.
New version of BCMerge allows lines to be moved left-to-right.
Merging new files between branch projects sometimes identified the wrong file as merge target (by ID rather than by name).
Re-creating a folder with case-changed name didn't work.
Single dot comment caused problems in SMTP.
Sort didn't work in the projects tab when no project was "interesting".
Resend request was sent to a defected project member, if he or she was the author of the missing script.
It was possible to execute join request from a project of a different name (only when the script was moved manually).
Removing and then creating a folder of the same name with different uppercasing ignored the change of case.
Membership history repair failed on some corrupt histories.
Allow multi-script selection in merge view. This makes possible selective merges of multiple scripts at once.
Project Repair repairs membership history of defected members.
Allow uninstall without defecting (very useful when moving co-op installation to a different machine).
Implemented new SCC interface v. 1.3. It's possible now to delete checked-out files from Visual Studio.
Code Co-op occasionally deadlocked in the background.
New project dialog didn't deal correctly with the attempt to nest projects.
Incorrect command availability during unfinished join (waiting for chunks).
Remove possible source of corruption from membership changes history.
In Sync/Merge view, the "Check out all files" button didn't work.
Email diagnostics failed with Microsoft Exchange.
Fixed broken link in Help.
Added All_Report to coopcmd. It generates a text file with the report from a specified view (tab).
"Folder delete" didn't remove folder from disk. Use heuristics to determine whether it's safe to delete the folder (don't delete if there are uncontrolled files inside).
"Automatically accept invitations" now available also from Program>Options.
When somebody is invited as observer, the "auto sync" option is automatically set (useful for inviting a central backup server).
Merge target (project) was not remembered across session.
Sorting by "change" in the check-in area put folders on top.
After "Restore Version" followed by "Uncheckout", deleted files were unnecessarily resuscitated (as not in project).
Dispatcher blocked after Windows logon password was changed and SMTP/POP3 was used.
Pasting a R/O file into a project did not remove the R/O attribute.
Sync/Merge page not always displayed after merge conflict.
When showing historical changes with BC Differ, it was possible to edit the right pane resulting in the corruption of the database copy of the file.
Duplicate chunks while unpacking full sync sometimes caused a lot of unnecessary resend requests.
Corrupt full synch blocked the project (it was impossible to visit it).
New merge type, Selective, to merge only changes made by a single script.
Merge type selection dropdown: Selective, Common Ancestor, and Cumulative.
Detect and mark local merge conflicts. Don't let the user dismiss them without running a UI merger.
Run auto-merge in a separate thread. If the merge succeeds, clear the "Conflict" state for the file.
Auto accept invitations in Project>Options
Bug fix in membership history. Bad membership histories caused Code Co-op to go into an infinite loop. Added detection of such problems and extended Project>Repair to fix them.
A Wiki site as a feature of a version control system?  What were we thinking?
Well, it started with text files. Code Co-op users quickly find out that they have a great tool for sharing notes. You jot a few lines, check the file in, and it's immediately available on your laptop, where you have a second enlistment. Or you add a text file with feature requests right in your development project. Soon enough you start using Code Co-op for documentation, or even to store bug reports.
We've been doing these things for some time, but we were always dissatisfied with the lack of formatting and structure afforded by text files. We needed something that's almost as easy to edit as text, but with the power and flexibility of an HTML document. Wiki was the obvious choice.
Here's what we did: We created a wiki parser and built a web browser control directly to Code Co-op. When Code Co-op enters a directory with a file called index.wiki, the parser parses it, converts into HTML, and the browser control displays it as a web page. The wiki file can be as simple as a plain text file. But with a little bit of easy-to-learn wiki markup, you can add simple formatting, embed links to other wiki pages, or display pictures.
But that's not all. Since the browser control is a full-blown internet browser, you can follow links from your local wiki pages to any external web site. You can also mix HTML or even JavaScript into your wiki pages.
Had we stopped at that, we would just have a great peer-to-peer wiki system--which we do! It can be used to create and share wiki sites without the need for servers. But we needed a "killer app" for our wiki. We wanted a wiki-based bug database.
What's the biggest shortcoming of bug databases? That they impose rigid structure on all bug reports. We wanted to be able to embed a screenshot or two in a report, a piece of preformatted code, a table, and so on. In other words, we wanted each bug report to be a wiki file. But we also wanted to be able to have a few "tuples" in each record--a "priority" field, an "assigned to" field, and so on. And, we had to be able to list the records based on the values of these fields. For instance, to list all open bugs assigned to Bartosz.
It sounds hard to believe, but we were actually able to accomplish it. We had to invent a mini-SQL language, which we call SQWiki, and do a few tricks, but the result is pretty specatacular considering the simplicity of the design.
As a side effect, Code Co-op now has a very flexible text-based database built into it. You can use it to store and retrieve any kinds of notes. And because it's so simple, you can do it without any training in database management.
What's the use of all the features if they are hard to find and hard to use? That's why we put so much effort in Code Co-op's user interface. Version 5.0 breaks new grounds in this respect.
The most spectacular feature is a split-pane history display. You select a script in the history pane and the lower pane immediately shows the list of files modified by that script. Double-click on a file in the lower pane and a differ opens, showing exactly how that file was changed by the selected script. The same mechanism works for scripts that are still in the inbox.
We made it very easy to view, save, compare and merge historical versions of files.
This ease of reviewing changes prompted us to simplify the synchronization process. You can preview an incoming script in the inbox and then execute it with a single click. Or you can skip previewing, only to later review the script in the history.
If the incoming script interferes with your local changes, the conflicting files are visible in the Local Merge area (used to be Synch Area). You can preview and correct the automatic merge, or you can use an external tool to perform the merge.
We listen to our users. We not always have the resources to address all the wishes, but we try.
A surprising number of our clients use Code Co-op to manage large numbers of projects. To make their lives easier, we added a special pane listing the most "interesting" projects. This pane is displayed in the main file area and in the proect area. It shows the projects that require user action, e.g., have pending scripts or checked-out files; as well as a few recently visited projects.
We created a command-line tool that can perform certain commands for all projects. Some users needed to be able to synchronize all projects in one pass. Others wanted to change their status to Observer before going on vacation (and then back to Voting Member) in all projects.
Joining a project has always been a bit of a problem. You had to have the project name just right, and the correct e-mail address of an existing member. Why not "invite" a new member instead of making him or her join? We finally implemented invitations. And not only that--we made it possible to invite a new member to ALL your projects using a command-line tool.
We've been under tremendous pressure from our users to improve the dispatching of scripts. In version 5.0 we made two major breakthroughs. We made the dispatcher non-blocking, and we added the SMTP/POP3 support.
There are times when the dispatcher has no idea how to dispatch a script. This happens because of configuration problems or user mistakes. In such cases, the dispatcher used to pop up a dialog box and wait. When that happened on an unattended hub, all traffic was stopped. Not any more!
Instead of a dialog, a baloon alert is displayed. If there's nobody to click on the baloon, the problem script goes into quarantine, and waits until somebody can deal with it.
The addition of SMTP/POP3 support to the dispatcher makes the use of e-mail for synchronization a breeze. In fact, if you can afford separate e-mail accounts, you should configure all your computers as e-mail peers and rely entirely on SMTP/POP3. This is one of these things that "just work". It's better than MAPI and sometimes even better than LAN.
The problem with branches is that they have to be merged. Even with the best of tools it's a tedious, error-prone, and menial task. Code Co-op was designed to avoid branching (except for the heavy-duty branching after a realease--when the project has to split into maintenance- and continuing-development version).
Neverthless, some merging is unavoidable, and we decided to make it as painless as possible. In version 5.0 a built-in merge tool (Beyond Compare Merger) can be used to perform merges. We also rationalized conflict resolution.
Occasionally two or more scripts miss each other. When that happens, Code Co-op creates a branch point. One of the branches becomes a trunk, the other has to be merged into the trunk.
In version 5.0, the person who is actively working on a losing branch may be able to postpone the execution of the incoming winning script and continue making side-branch check-ins. At some point, of course, a merge should be performed.
A merge is as easy as selecting the branch script in the history pane, selecting a file in the lower pane, and clicking the merge button to start an (external) file merger.
Merging is also easy when you have a project that was created by branching from some other project. You can open the Branch Merge view (either from History, or from the View menu), and select a branch project. You can then pick a script and individual files that have to be merged.